From c520284035a6b156aa0ad72a4d0446dc6cdb7fe0 Mon Sep 17 00:00:00 2001 From: vdoleans Date: Mon, 4 Jun 2018 14:38:23 +0200 Subject: [PATCH 1/8] Exception no send after failed commit --- .../com/amadeus/session/ErrorTracker.java | 19 +- .../com/amadeus/session/ResetManager.java | 13 ++ .../com/amadeus/session/SessionManager.java | 187 +++++++++--------- .../redis/RedisSessionRepository.java | 5 +- .../session/servlet/HttpRequestWrapper.java | 49 +++-- .../session/servlet/SessionFilter.java | 102 +++++----- .../session/servlet/SessionHelpers.java | 141 ++++++------- .../session/servlet/SessionHelpersFacade.java | 67 +++---- 8 files changed, 297 insertions(+), 286 deletions(-) diff --git a/session-replacement/src/main/java/com/amadeus/session/ErrorTracker.java b/session-replacement/src/main/java/com/amadeus/session/ErrorTracker.java index 1c295df..c29d66e 100644 --- a/session-replacement/src/main/java/com/amadeus/session/ErrorTracker.java +++ b/session-replacement/src/main/java/com/amadeus/session/ErrorTracker.java @@ -2,15 +2,21 @@ import java.util.concurrent.ConcurrentLinkedQueue; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * The class is used to determine if the application is in error or not * * If the number of error stored during the delay reach the max , the application is in error * - * @param period - * Time in milliseconds while items are kept - * @param max - * If the number of items is more than the max value the Tracker is considered in error + * period + * + * Time in milliseconds while items are kept + * + * max + * + * If the number of items is more than the max value the Tracker is considered in error * */ @@ -21,6 +27,8 @@ public ErrorTracker(int period, int max) { this.max = max; } + private static final Logger logger = LoggerFactory.getLogger(ErrorTracker.class); + private ConcurrentLinkedQueue list = new ConcurrentLinkedQueue(); /** @@ -37,7 +45,7 @@ public ErrorTracker(int period, int max) { * The parameter is a time with the format millisecond from 1900 ( System.currentTimeMillis() ) This method add an * event into the Tracker and remove all the old event with the followinf criteria * - * now - oldevent > period will be + * now - oldevent superior to period will be * * removed * @@ -66,6 +74,7 @@ public int size() { } public void reset() { + logger.debug("reset of the ErrorTracker"); list.clear(); } } diff --git a/session-replacement/src/main/java/com/amadeus/session/ResetManager.java b/session-replacement/src/main/java/com/amadeus/session/ResetManager.java index eeb8198..a85c629 100644 --- a/session-replacement/src/main/java/com/amadeus/session/ResetManager.java +++ b/session-replacement/src/main/java/com/amadeus/session/ResetManager.java @@ -2,6 +2,9 @@ import static com.codahale.metrics.MetricRegistry.name; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + import com.codahale.metrics.JmxReporter; import com.codahale.metrics.Meter; import com.codahale.metrics.MetricRegistry; @@ -9,6 +12,8 @@ public class ResetManager { private final MetricRegistry monitoring; + private Lock lock = new ReentrantLock(); + private JmxReporter reporter; private final ErrorTracker errorTracker; @@ -84,4 +89,12 @@ public void notConnected() { notConnected_meter.mark(); } + public boolean tryLock() { + return lock.tryLock(); + } + + public void unlock() { + lock.unlock(); + } + } diff --git a/session-replacement/src/main/java/com/amadeus/session/SessionManager.java b/session-replacement/src/main/java/com/amadeus/session/SessionManager.java index 2cc631d..eb61c80 100644 --- a/session-replacement/src/main/java/com/amadeus/session/SessionManager.java +++ b/session-replacement/src/main/java/com/amadeus/session/SessionManager.java @@ -10,7 +10,6 @@ import javax.servlet.ServletContext; -import org.apache.commons.pool2.TrackedUse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; @@ -22,48 +21,42 @@ import com.codahale.metrics.Timer; /** - * Main class responsible for managing sessions. The class offers strategy for - * retrieving, creating, propagating and deleting session. It also offers - * services for scheduling and executing task asynchronously. + * Main class responsible for managing sessions. The class offers strategy for retrieving, creating, propagating and + * deleting session. It also offers services for scheduling and executing task asynchronously. *

- * In case of servlet engines, one session manager will be created per - * {@link ServletContext}. + * In case of servlet engines, one session manager will be created per {@link ServletContext}. *

* The manager provides following metrics: *

    - *
  • `com.amadeus.session.created` measures total number of created sessions - * as well as rate of sessions created in last 1, 5 and 15 minutes - *
  • `com.amadeus.session.deleted` measures total number of deleted sessions - * as well as rate of sessions measures rate of sessions deleted in last 1, 5 - * and 15 minutes - *
  • `com.amadeus.session.missing` measures total number of session which were - * not found in repository, as measures rate of such occurrences in last 1, 5 and - * 15 minutes - *
  • `com.amadeus.session.retrieved` measures total number of session - * retrievals as well as measures rate of sessions retrieval from store in last - * 1, 5 and 15 minutes - *
  • `com.amadeus.session.timers.commit` measures histogram (distribution) of - * elapsed time during commit as well as total number of commits and rate of - * commits over last 1, 5 and 15 minutes - *
  • `com.amadeus.session.timers.fetch` measures histogram (distribution) of - * elapsed time during fetch of session data from repository as well as total - * number of fetch requests and rate of fetch requests over last 1, 5 and 15 - * minutes + *
  • `com.amadeus.session.created` measures total number of created sessions as well as rate of sessions created in + * last 1, 5 and 15 minutes + *
  • `com.amadeus.session.deleted` measures total number of deleted sessions as well as rate of sessions measures rate + * of sessions deleted in last 1, 5 and 15 minutes + *
  • `com.amadeus.session.missing` measures total number of session which were not found in repository, as measures + * rate of such occurrences in last 1, 5 and 15 minutes + *
  • `com.amadeus.session.retrieved` measures total number of session retrievals as well as measures rate of sessions + * retrieval from store in last 1, 5 and 15 minutes + *
  • `com.amadeus.session.timers.commit` measures histogram (distribution) of elapsed time during commit as well as + * total number of commits and rate of commits over last 1, 5 and 15 minutes + *
  • `com.amadeus.session.timers.fetch` measures histogram (distribution) of elapsed time during fetch of session data + * from repository as well as total number of fetch requests and rate of fetch requests over last 1, 5 and 15 minutes *
*/ public class SessionManager implements Closeable { private static final Logger logger = LoggerFactory.getLogger(SessionManager.class); static final String SESSIONS_METRIC_PREFIX = "com.amadeus.session"; - - - private static final String COMMIT_TIMER_METRIC = name(SESSIONS_METRIC_PREFIX, "timer", "commit"); + private static final String FETCH_TIMER_METRIC = name(SESSIONS_METRIC_PREFIX, "timer", "fetch"); + private static final String CREATED_SESSIONS_METRIC = name(SESSIONS_METRIC_PREFIX, "created"); + private static final String DELETED_SESSIONS_METRIC = name(SESSIONS_METRIC_PREFIX, "deleted"); + private static final String MISSING_SESSIONS_METRIC = name(SESSIONS_METRIC_PREFIX, "missing"); + private static final String RETRIEVED_SESSIONS_METRIC = name(SESSIONS_METRIC_PREFIX, "retrieved"); static final String INVALIDATION_ON_EXPIRY_ERRORS_METRIC = name(SESSIONS_METRIC_PREFIX, "invalidation", "errors", @@ -74,20 +67,33 @@ public class SessionManager implements Closeable { static final String SESSION_PROPAGATED = "com.amadeus.session.sessionPropagated"; protected final SessionRepository repository; + protected final SessionNotifier notifier; + protected final SessionTracking tracking; + protected final SessionFactory factory; + protected final ExecutorFacade executors; + protected final SessionConfiguration configuration; + protected final SerializerDeserializer serializerDeserializer; private final Meter createdSessions; + private final Meter deletedSessions; + private final Meter retrievedSessions; + private final Meter invalidationErrors; + private final Meter invalidationExpiryErrors; + private final Meter missingSessions; + private final Timer commitTimer; + private final Timer fetchTimer; private final MetricRegistry monitoring; @@ -104,10 +110,9 @@ public class SessionManager implements Closeable { * @param factory * creates memory representation of session * @param repository - * repository should be namespace aware - if two - * {@link SessionManager} from different namespaces request access to - * session with same id, repository should give different sessions - * (unless a special configuration overrides this). + * repository should be namespace aware - if two {@link SessionManager} from different namespaces request + * access to session with same id, repository should give different sessions (unless a special configuration + * overrides this). * @param tracking * propagates session information to clients * @param notifier @@ -118,7 +123,7 @@ public class SessionManager implements Closeable { * the class loader to use */ public SessionManager(ExecutorFacade executors, SessionFactory factory, SessionRepository repository, - SessionTracking tracking, SessionNotifier notifier, SessionConfiguration configuration, ClassLoader classLoader ) { + SessionTracking tracking, SessionNotifier notifier, SessionConfiguration configuration, ClassLoader classLoader) { this.repository = repository; this.tracking = tracking; @@ -129,7 +134,7 @@ public SessionManager(ExecutorFacade executors, SessionFactory factory, SessionR this.classLoader = classLoader; monitoring = new MetricRegistry(); - + createdSessions = monitoring.meter(CREATED_SESSIONS_METRIC); deletedSessions = monitoring.meter(DELETED_SESSIONS_METRIC); retrievedSessions = monitoring.meter(RETRIEVED_SESSIONS_METRIC); @@ -138,10 +143,9 @@ public SessionManager(ExecutorFacade executors, SessionFactory factory, SessionR invalidationExpiryErrors = monitoring.meter(INVALIDATION_ON_EXPIRY_ERRORS_METRIC); commitTimer = monitoring.timer(COMMIT_TIMER_METRIC); fetchTimer = monitoring.timer(FETCH_TIMER_METRIC); - - serializerDeserializer = configuration.isUsingEncryption() ? - new EncryptingSerializerDeserializer() : - new JdkSerializerDeserializer(); + + serializerDeserializer = configuration.isUsingEncryption() ? new EncryptingSerializerDeserializer() + : new JdkSerializerDeserializer(); serializerDeserializer.setSessionManager(this); factory.setSessionManager(this); @@ -150,8 +154,7 @@ public SessionManager(ExecutorFacade executors, SessionFactory factory, SessionR } /** - * Starts monitoring this session manager. The method will expose all metrics - * through JMX. + * Starts monitoring this session manager. The method will expose all metrics through JMX. */ private void startMonitoring() { executors.startMetrics(monitoring); @@ -169,14 +172,13 @@ private String getJmxDomain() { } /** - * Fetch the session from the repository. If session was with given id - * retrieved, but has expired, it will be cleaned up. + * Fetch the session from the repository. If session was with given id retrieved, but has expired, it will be cleaned + * up. * * @param sessionId * session id * @param updateTimestamp - * true if the session timestamp should be updated - * (usually at the start of request) + * true if the session timestamp should be updated (usually at the start of request) * @return session or null if session is not in repository. */ private RepositoryBackedSession fetchSession(String sessionId, boolean updateTimestamp) { @@ -237,15 +239,13 @@ private RepositoryBackedSession newSession(String sessionId) { } /** - * Builds or retrieves session. If session is found in repository, it is - * retrieved, if not, and create parameter is set to true, then a - * new session is created. Session id is generated according to + * Builds or retrieves session. If session is found in repository, it is retrieved, if not, and create parameter is + * set to true, then a new session is created. Session id is generated according to * {@link SessionTracking} implementation. *

- * In some cases, in servlet engine, request can be forwarded from one web - * application to another one. In this case, the first web application that - * received request, is responsible for managing session id, and other web - * application down the chain will reuse this id. + * In some cases, in servlet engine, request can be forwarded from one web application to another one. In this case, + * the first web application that received request, is responsible for managing session id, and other web application + * down the chain will reuse this id. * * @param request * the request being servet @@ -256,7 +256,8 @@ private RepositoryBackedSession newSession(String sessionId) { * * @return existing or new session */ - public RepositoryBackedSession getSession(RequestWithSession request, boolean create, SessionTracking.IdAndSource forceId) { + public RepositoryBackedSession getSession(RequestWithSession request, boolean create, + SessionTracking.IdAndSource forceId) { SessionTracking.IdAndSource id = retrieveId(request, forceId); RepositoryBackedSession session = null; if (id != null && id.id != null) { @@ -268,9 +269,9 @@ public RepositoryBackedSession getSession(RequestWithSession request, boolean cr request.repositoryChecked(); } } else { - // Session is null, assume default tracking + // Session is null, assume default tracking putIdInLoggingMdc(null); - request.setRequestedSessionId(null, tracking.isCookieTracking()); + request.setRequestedSessionId(null, tracking.isCookieTracking()); } if (session == null && create) { if (forceId == null) { @@ -289,8 +290,7 @@ public RepositoryBackedSession getSession(RequestWithSession request, boolean cr } /** - * Changes session id of the passed session. Session id can change only once - * per request. + * Changes session id of the passed session. Session id can change only once per request. * * @param session * the session whose id needs to change @@ -306,8 +306,8 @@ private void putIdInLoggingMdc(String id) { } /** - * Retrieves id from request. The forceId parameter is used to force usage of - * certain id (e.g. when forwarding request from one web app to another). + * Retrieves id from request. The forceId parameter is used to force usage of certain id (e.g. when forwarding request + * from one web app to another). * * @param request * the request that contains session id @@ -326,8 +326,7 @@ private SessionTracking.IdAndSource retrieveId(RequestWithSession request, Sessi } /** - * Propagates the session id to the response. The propagation is done once per - * request. + * Propagates the session id to the response. The propagation is done once per request. * * @param request * the current request @@ -342,8 +341,8 @@ public void propagateSession(RequestWithSession request, ResponseWithSessionId r } /** - * Deletes session from repository and performs orderly cleanup. Called when - * session expires or when application closes + * Deletes session from repository and performs orderly cleanup. Called when session expires or when application + * closes * * @param sessionId * the id of the session to delete @@ -361,11 +360,10 @@ public void delete(String sessionId, boolean expired) { } private void markSessionDeletion(String sessionId) { - logger.info("deleting session with sessionId: '{}'", sessionId ); + logger.info("deleting session with sessionId: '{}'", sessionId); deletedSessions.mark(); } - /** * Called when request has been finished. Notifies repository of that fact. */ @@ -374,12 +372,10 @@ public void requestFinished() { } /** - * Executes task in separate thread. This is used to launch blocking or - * long-running tasks. + * Executes task in separate thread. This is used to launch blocking or long-running tasks. * * @param timer - * if not null, the time to execute task will be measured and stored - * under timer with given name + * if not null, the time to execute task will be measured and stored under timer with given name * @param task * the task to run * @return the future for the runnable. Note that runnable has no result. @@ -393,18 +389,15 @@ public Future submit(String timer, Runnable task) { } /** - * Schedules the tasks to execute with a {@link ScheduledExecutorService} with - * the specified period. + * Schedules the tasks to execute with a {@link ScheduledExecutorService} with the specified period. * * @param timer - * if not null, the time to execute task will be measured and stored - * under timer with given name + * if not null, the time to execute task will be measured and stored under timer with given name * @param task * the task to run * @param period * period between invocations in seconds - * @return the scheduled future for the task. Note that runnable has no - * result. + * @return the scheduled future for the task. Note that runnable has no result. */ public ScheduledFuture schedule(String timer, Runnable task, long period) { if (timer != null) { @@ -454,8 +447,7 @@ public SessionNotifier getNotifier() { } /** - * Calls {@link Committer} for the passed {@link RepositoryBackedSession} and - * measures time of execution. + * Calls {@link Committer} for the passed {@link RepositoryBackedSession} and measures time of execution. * * @param session * the session to commit @@ -468,6 +460,7 @@ public void invokeCommit(RepositoryBackedSession session) { session.getCommitter().run(); // NOSONAR we use run intentionally } catch (Exception e) { // NOSONAR Any exception can occur here logger.error("Exception occured while commiting sessionId: '" + session.getId() + "'", e); + throw e; } } @@ -490,8 +483,7 @@ public ClassLoader getSessionClassLoader() { } /** - * Serialiazer/deserializer to use when storing to repository. Serialaizer and - * deserializers can be configured. + * Serialiazer/deserializer to use when storing to repository. Serialaizer and deserializers can be configured. * * @return serialiazer/deserializer to use */ @@ -504,11 +496,11 @@ public SerializerDeserializer getSerializerDeserializer() { */ final class RunnableWithTimer implements Runnable { final Runnable task; + final Timer timer; /** - * Helper {@link Runnable} class used to measure the execution time of - * passed task and stores it in metrics. + * Helper {@link Runnable} class used to measure the execution time of passed task and stores it in metrics. * * @param timerName * name of the timer where the processing time is stored @@ -533,9 +525,8 @@ public void run() { } /** - * Called by {@link RepositoryBackedSession} when a conflict occurs during - * invalidation of session. Conflict may be due to fact that session is stil - * used. + * Called by {@link RepositoryBackedSession} when a conflict occurs during invalidation of session. Conflict may be + * due to fact that session is stil used. * * @param session * the session to remove @@ -574,21 +565,20 @@ public String encodeUrl(RequestWithSession request, String url) { return tracking.encodeUrl(request, url); } - - /** * Called to shutdown the session manager and perform needed cleanup. */ - + public void reset() { - if (reporter != null) { - reporter.stop(); - reporter.close(); - } - - repository.reset(); - executors.shutdown(); - } + if (reporter != null) { + reporter.stop(); + reporter.close(); + } + + repository.reset(); + executors.shutdown(); + } + /** * Called to shutdown the session manager and perform needed cleanup. */ @@ -610,8 +600,7 @@ public void close() { } /** - * Changes session id of the passed session. Session id can change only once - * per request. + * Changes session id of the passed session. Session id can change only once per request. * * @param session * the session whose id needs to change @@ -653,12 +642,12 @@ public String toString() { } public void remove(SessionData sessionData) { - markSessionDeletion( sessionData.getId() ); + markSessionDeletion(sessionData.getId()); getRepository().remove(sessionData); } - - public boolean isConnected(){ + + public boolean isConnected() { return this.repository.isConnected(); } - + } diff --git a/session-replacement/src/main/java/com/amadeus/session/repository/redis/RedisSessionRepository.java b/session-replacement/src/main/java/com/amadeus/session/repository/redis/RedisSessionRepository.java index f0bc939..c6dfd07 100644 --- a/session-replacement/src/main/java/com/amadeus/session/repository/redis/RedisSessionRepository.java +++ b/session-replacement/src/main/java/com/amadeus/session/repository/redis/RedisSessionRepository.java @@ -26,8 +26,6 @@ import com.codahale.metrics.MetricFilter; import com.codahale.metrics.MetricRegistry; -import redis.clients.jedis.exceptions.JedisException; - /** * Main class for implementing Redis repository logic. */ @@ -544,6 +542,7 @@ static String extractSessionId(String body) { * Changes session id. This renames key in redis and publishes the redis event if other nodes need to be notified. * * @param sessionData + * content of the session */ @Override public void sessionIdChange(SessionData sessionData) { @@ -557,7 +556,7 @@ public boolean isConnected() { try { redis.info("server"); return true; - } catch (JedisException e) { + } catch (Exception e) { return false; } } diff --git a/session-replacement/src/main/java/com/amadeus/session/servlet/HttpRequestWrapper.java b/session-replacement/src/main/java/com/amadeus/session/servlet/HttpRequestWrapper.java index ef9c6e7..c6ac68f 100644 --- a/session-replacement/src/main/java/com/amadeus/session/servlet/HttpRequestWrapper.java +++ b/session-replacement/src/main/java/com/amadeus/session/servlet/HttpRequestWrapper.java @@ -14,24 +14,35 @@ import com.amadeus.session.SessionTracking; /** - * Wrapper for {@link HttpServletRequest} that implements storing of sessions in - * repository. This class implements following commit logic: propagate session - * to response, store session in repository, perform cleanups as request + * Wrapper for {@link HttpServletRequest} that implements storing of sessions in repository. This class implements + * following commit logic: propagate session to response, store session in repository, perform cleanups as request * processing has finished. */ class HttpRequestWrapper extends HttpServletRequestWrapper implements RequestWithSession { private static final Logger logger = LoggerFactory.getLogger(HttpRequestWrapper.class); + RepositoryBackedHttpSession session; + boolean committed; + private HttpResponseWrapper response; + private final HttpRequestWrapper embeddedRequest; + private final SessionManager manager; + private final ServletContext servletContext; + private boolean propagateOnCreate; + private boolean propagated; + private boolean idRetrieved; + private String retrievedId; + private boolean isRetrievedIdFromCookie; + private boolean repositoryChecked; /** @@ -154,15 +165,19 @@ public void commit() { * Implementation of commit. */ void doCommit() { - if (committed) { - return; - } - // we propagate the session, and that will trigger storage - if (!propagateSession()) { - storeSession(); + try { + + if (committed) { + return; + } + // we propagate the session, and that will trigger storage + if (!propagateSession()) { + storeSession(); + } + } finally { + committed = true; + manager.requestFinished(); } - committed = true; - manager.requestFinished(); } /** @@ -176,6 +191,7 @@ void storeSession() { session.commit(); } catch (Exception e) { // NOSONAR - some error occured, log it logger.warn("cannot store session: {}", session, e); + throw e; } } else { logger.debug("session was null, nothing to commit"); @@ -203,9 +219,8 @@ public ServletContext getServletContext() { } /** - * Get wrapped request if it is an {@link HttpRequestWrapper}. - * Returns null if wrapped wrapped request was - * not HttpRequestWrapper. + * Get wrapped request if it is an {@link HttpRequestWrapper}. Returns null if wrapped wrapped request + * was not HttpRequestWrapper. * * @return */ @@ -223,9 +238,8 @@ public boolean isPropagateOnCreate() { } /** - * Controls if session should be propagated on create. Session should be - * propagated on request if {@link #propagateSession()} method was called - * (i.e. if there an event occurred that requires session propagation). + * Controls if session should be propagated on create. Session should be propagated on request if + * {@link #propagateSession()} method was called (i.e. if there an event occurred that requires session propagation). * * @param propagate */ @@ -295,6 +309,7 @@ public void repositoryChecked() { /** * Called to encode URL. This is used when URL session propagation is used. + * * @param url * @return */ diff --git a/session-replacement/src/main/java/com/amadeus/session/servlet/SessionFilter.java b/session-replacement/src/main/java/com/amadeus/session/servlet/SessionFilter.java index 616fbec..3aac63f 100644 --- a/session-replacement/src/main/java/com/amadeus/session/servlet/SessionFilter.java +++ b/session-replacement/src/main/java/com/amadeus/session/servlet/SessionFilter.java @@ -25,34 +25,34 @@ import com.amadeus.session.SessionManager; import redis.clients.jedis.exceptions.JedisException; -import redis.clients.jedis.exceptions.JedisNoReachableClusterNodeException; /** * Filter that wraps the httpRequest to enable Http Session caching. * - * Note that it won't wrap the request twice even if the filter is called two - * times. + * Note that it won't wrap the request twice even if the filter is called two times. * * @see ServletRequestWrapper */ public class SessionFilter implements Filter { ServletContext servletContext; + private static final Logger logger = LoggerFactory.getLogger(SessionFilter.class); + /** - * Initializes session management based on repository for current servlet - * context. + * Initializes session management based on repository for current servlet context. * * @param config * The filter configuration. */ @Override public void init(FilterConfig config) { + logger.warn("init"); initForSession(config); } /** - * Initializes session management based on repository for current servlet - * context. This method is internal method for session management. + * Initializes session management based on repository for current servlet context. This method is internal method for + * session management. * * @param config * The filter configuration. @@ -60,13 +60,12 @@ public void init(FilterConfig config) { public void initForSession(FilterConfig config) { if (servletContext == null) { servletContext = config.getServletContext(); - initSessionManagement(servletContext); + initSessionManagement(servletContext); } } /** - * Implements wrapping of HTTP request and enables handling of sessions based - * on repository. + * Implements wrapping of HTTP request and enables handling of sessions based on repository. * * @param originalRequest * The request to wrap @@ -85,49 +84,62 @@ public void doFilter(ServletRequest originalRequest, ServletResponse originalRes ServletRequest request = prepareRequest(originalRequest, originalResponse, servletContext); ServletResponse response = prepareResponse(request, originalResponse, servletContext); SessionManager sessionManager = (SessionManager)servletContext.getAttribute(Attributes.SESSION_MANAGER); - - + try { // Call next filter in chain chain.doFilter(request, response); } finally { - // Commit the session. Implementation expects that request has been - // wrapped and that originalRequest is not an OffloadSessionHttpServletRequest - try{ - commitRequest(request, originalRequest, servletContext); - } - catch ( Exception e ) { - logger.error("Error into doFilter" , e ); - if ( e instanceof JedisException || (e.getClass().getName().indexOf("jedis.exceptions") != -1 )) { - synchronized (this) { - - SessionManager sessionManagercurrent = (SessionManager)servletContext.getAttribute(Attributes.SESSION_MANAGER); - if ( sessionManagercurrent == sessionManager ) { - - ResetManager resetManager = (ResetManager)servletContext.getAttribute(Attributes.ResetManager); - ErrorTracker errorTracker = resetManager.getErrorTracker(); - errorTracker.addError( System.currentTimeMillis() ); - if ( errorTracker.reachLimits() ) { - if (sessionManagercurrent != null) { - sessionManagercurrent.reset(); - } - initSessionManagementReset(servletContext,true); - } else { - logger.warn("Error into redis but the limits is not reach:" + errorTracker.size() ); - } - - } - } - } - throw e; - } - + try { + commitRequest(request, originalRequest, servletContext); + } catch (Exception e) { + logger.error("Error into commit doFilter", e); + ext(sessionManager, e); + throw e; + } + } + + } + + private void ext(SessionManager sessionManager, Exception e) { + if (e instanceof JedisException || (e.getClass().getName().indexOf("jedis.exceptions") != -1)) { + + ResetManager resetManager = (ResetManager)servletContext.getAttribute(Attributes.ResetManager); + SessionManager sessionManagercurrent = (SessionManager)servletContext.getAttribute(Attributes.SESSION_MANAGER); + if (sessionManagercurrent == sessionManager) { + + ErrorTracker errorTracker = resetManager.getErrorTracker(); + errorTracker.addError(System.currentTimeMillis()); + if (errorTracker.reachLimits()) { + + boolean lock = resetManager.tryLock(); + if (lock) { + try { + + if (sessionManagercurrent != null) { + sessionManagercurrent.reset(); + } + initSessionManagementReset(servletContext, true); + + } finally { + resetManager.unlock(); + } + + } else { + logger.warn("already lokked"); + } + } else { + logger.warn("Error into redis but the limits is not reach:" + errorTracker.size()); + } + + } else { + + } + } } /** - * No specific processing is done when this filter is being taken out of - * service. + * No specific processing is done when this filter is being taken out of service. */ @Override public void destroy() { diff --git a/session-replacement/src/main/java/com/amadeus/session/servlet/SessionHelpers.java b/session-replacement/src/main/java/com/amadeus/session/servlet/SessionHelpers.java index fb52f53..809a330 100644 --- a/session-replacement/src/main/java/com/amadeus/session/servlet/SessionHelpers.java +++ b/session-replacement/src/main/java/com/amadeus/session/servlet/SessionHelpers.java @@ -1,6 +1,5 @@ package com.amadeus.session.servlet; -import static com.codahale.metrics.MetricRegistry.name; import static java.lang.invoke.MethodType.methodType; import java.io.IOException; @@ -28,7 +27,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.amadeus.session.ErrorTracker; import com.amadeus.session.ExecutorFacade; import com.amadeus.session.ResetManager; import com.amadeus.session.SessionConfiguration; @@ -39,36 +37,35 @@ import com.amadeus.session.SessionRepositoryFactory; import com.amadeus.session.SessionTracking; import com.amadeus.session.repository.inmemory.InMemoryRepository; -import com.codahale.metrics.JmxReporter; -import com.codahale.metrics.Meter; -import com.codahale.metrics.MetricRegistry; - -import redis.clients.jedis.exceptions.JedisNoReachableClusterNodeException; /** - * This class contains various methods that are called either from session - * enabled filters, or from code injected by SessionAgent. + * This class contains various methods that are called either from session enabled filters, or from code injected by + * SessionAgent. */ public final class SessionHelpers { private static final Logger logger = LoggerFactory.getLogger(SessionHelpers.class); static final String DUMMY_ATTRIBUTE = "com.amadeus.session.dummy"; + static final String SESSION_HELPER_METHODS = "com.amadeus.session.servlet.SessionHelpers.methods"; + static final String DEFAULT_REPOSITORY_FACTORY = "com.amadeus.session.repository.inmemory.InMemoryRepositoryFactory"; + static final String INTROSPECTING_LISTENERS = "com.amadeus.session.introspected.listeners"; + static final String REQUEST_WRAPPED_ATTRIBUTE = HttpRequestWrapper.class.getName(); + static final String SESSION_CONFIGURATION = SessionConfiguration.class.getName(); + static final String SESSION_HELPERS = SessionHelpers.class.getName(); private boolean interceptListeners; /** - * This method is called from {@link SessionFilter} or from {@link Filter} - * implementations modified by SessionAgent. The method wraps - * {@link ServletRequest} in {@link HttpRequestWrapper}. + * This method is called from {@link SessionFilter} or from {@link Filter} implementations modified by SessionAgent. + * The method wraps {@link ServletRequest} in {@link HttpRequestWrapper}. *

- * The method will wrap request at most once per request and will only wrap - * instances of {@link HttpServletRequest}. + * The method will wrap request at most once per request and will only wrap instances of {@link HttpServletRequest}. * * @param request * request received by filter @@ -122,9 +119,8 @@ private static HttpRequestWrapper wrapRequest(ServletRequest request, ServletCon } /** - * This method is called from {@link SessionFilter} or from {@link Filter} - * implementations modified by SessionAgent. The method retrieves response - * stored in {@link HttpRequestWrapper}. + * This method is called from {@link SessionFilter} or from {@link Filter} implementations modified by SessionAgent. + * The method retrieves response stored in {@link HttpRequestWrapper}. * * @param request * request received by filter @@ -140,25 +136,23 @@ public ServletResponse prepareResponse(ServletRequest request, ServletResponse r } /** - * This method initializes session management for a given - * {@link ServletContext}. This method is called from - * {@link SessionFilter#init(javax.servlet.FilterConfig)}. The method will - * create and configure {@link SessionManager} if needed. + * This method initializes session management for a given {@link ServletContext}. This method is called from + * {@link SessionFilter#init(javax.servlet.FilterConfig)}. The method will create and configure {@link SessionManager} + * if needed. * * @param servletContext * the active servlet context * @return list of method handles for publicly accessible methods * */ - public MethodHandle[] initSessionManagement(ServletContext servletContext ) { - return initSessionManagement( servletContext , false ); + public MethodHandle[] initSessionManagement(ServletContext servletContext) { + return initSessionManagement(servletContext, false); } - + /** - * This method initializes session management for a given - * {@link ServletContext}. This method is called from - * {@link SessionFilter#init(javax.servlet.FilterConfig)}. The method will - * create and configure {@link SessionManager} if needed. + * This method initializes session management for a given {@link ServletContext}. This method is called from + * {@link SessionFilter#init(javax.servlet.FilterConfig)}. The method will create and configure {@link SessionManager} + * if needed. * * @param servletContext * the active servlet context @@ -167,29 +161,26 @@ public MethodHandle[] initSessionManagement(ServletContext servletContext ) { * @return list of method handles for publicly accessible methods * */ - public MethodHandle[] initSessionManagement(ServletContext servletContext , boolean reset) { - + public MethodHandle[] initSessionManagement(ServletContext servletContext, boolean reset) { + logger.warn("initSessionManagement start."); ResetManager resetManager = (ResetManager)servletContext.getAttribute(Attributes.ResetManager); - if ( resetManager == null ) { + if (resetManager == null) { SessionConfiguration conf = initConf(servletContext); ExecutorFacade executors = new ExecutorFacade(conf); - resetManager = new ResetManager (executors,conf); + resetManager = new ResetManager(executors, conf); servletContext.setAttribute(Attributes.ResetManager, resetManager); } else { resetManager.reset(); } - - - - + MethodHandle[] methods = (MethodHandle[])servletContext.getAttribute(SESSION_HELPER_METHODS); - if (methods == null || reset ) { + if (methods == null || reset) { synchronized (this) { methods = prepareMethodCalls(servletContext); } servletContext.setAttribute(SESSION_HELPERS, this); ServletContextDescriptor scd = getDescriptor(servletContext); - if ( !reset ) { + if (!reset) { setupContext(servletContext); } SessionNotifier notifier = new HttpSessionNotifier(scd); @@ -200,30 +191,29 @@ public MethodHandle[] initSessionManagement(ServletContext servletContext , bool SessionTracking tracking = getTracking(servletContext, conf); ExecutorFacade executors = new ExecutorFacade(conf); - + ClassLoader classLoader = classLoader(servletContext); SessionManager sessionManagement = new SessionManager(executors, factory, repository, tracking, notifier, conf, classLoader); interceptListeners = conf.isInterceptListeners(); - servletContext.setAttribute(Attributes.SESSION_MANAGER, sessionManagement); - if ( sessionManagement.isConnected() ) { - logger.warn("The connection to redis is ok."); + + if (sessionManagement.isConnected()) { + servletContext.setAttribute(Attributes.SESSION_MANAGER, sessionManagement); + logger.warn("The connection to redis is ok."); resetManager.connected(); } else { logger.warn("The connection to redis is ko."); resetManager.notConnected(); } - - - + } + logger.warn("initSessionManagement end."); return methods; } /** - * This method introspects this class and records {@link MethodHandle} of - * public methods. This allows direct invocation of said methods from - * instrumented classes. + * This method introspects this class and records {@link MethodHandle} of public methods. This allows direct + * invocation of said methods from instrumented classes. * * @param servletContext * the active servlet context @@ -258,9 +248,8 @@ private MethodHandle[] prepareMethodCalls(ServletContext servletContext) { } /** - * Obtains {@link SessionTracking} from {@link SessionConfiguration}. It can - * be configured either as the element of the {@link SessionPropagation} - * enumeration or as fully qualified class name of the implementation. + * Obtains {@link SessionTracking} from {@link SessionConfiguration}. It can be configured either as the element of + * the {@link SessionPropagation} enumeration or as fully qualified class name of the implementation. * * @param servletContext * used to initialize tracking @@ -387,8 +376,7 @@ private static Object newInstance(ServletContext servletContext, String implemen } /** - * Retrieves class loader from servlet context if it is servlet 3.x or from - * current thread otherwise + * Retrieves class loader from servlet context if it is servlet 3.x or from current thread otherwise * * @param servletContext * active servlet context @@ -405,8 +393,7 @@ private static ClassLoader classLoader(ServletContext servletContext) { } /** - * Initializes session configuration if it has not already been done for the - * current servlet context + * Initializes session configuration if it has not already been done for the current servlet context * * @param context * active servlet context @@ -439,21 +426,21 @@ public Object source() { } /** - * Commits request and stores session in repository. This method is called - * from the filter. The commit is only done if the filter is the one that - * wrapped the request into HttpRequestWrapper. + * Commits request and stores session in repository. This method is called from the filter. The commit is only done if + * the filter is the one that wrapped the request into HttpRequestWrapper. *

- * The logic to check if the caller filter is the one that wrapped request is - * based on requirement that original request and the one used by filter are - * different and that original request is not {@link HttpRequestWrapper}. + * The logic to check if the caller filter is the one that wrapped request is based on requirement that original + * request and the one used by filter are different and that original request is not {@link HttpRequestWrapper}. * * @param request * potentially wrapped request * @param oldRequest * original request received by filter + * @throws IOException + * in case on redis connection failure */ - public void commitRequest(ServletRequest request, ServletRequest oldRequest) throws IOException { - // we are looking for identity below + public void commitRequest(ServletRequest request, ServletRequest oldRequest) throws IOException { + // we are looking for identity below if (request != oldRequest && request instanceof HttpRequestWrapper) { // NOSONAR HttpRequestWrapper httpRequestWrapper = (HttpRequestWrapper)request; try { @@ -472,8 +459,7 @@ public void commitRequest(ServletRequest request, ServletRequest oldRequest) thr } /** - * This method is called inside Servlet 2.5 containers to collect information - * about existing HttpServletListeners. + * This method is called inside Servlet 2.5 containers to collect information about existing HttpServletListeners. * * @param context * current servlet context @@ -503,10 +489,9 @@ static void findListenersByIntercepting(ServletContext context, HttpServletReque } /** - * Call to this method is injected by agent into implementations of - * {@link HttpSessionAttributeListener} and {@link HttpSessionListener} inside - * Servlet 2.5 containers. It's roll is to collect session listeners so they - * can be invoked by the library when it manages sessions. + * Call to this method is injected by agent into implementations of {@link HttpSessionAttributeListener} and + * {@link HttpSessionListener} inside Servlet 2.5 containers. It's roll is to collect session listeners so they can be + * invoked by the library when it manages sessions. * * @param caller * listener where event was received @@ -526,10 +511,8 @@ public void interceptHttpListener(EventListener caller, HttpSessionEvent event) } /** - * This method retrieves {@link ServletContextDescriptor} for a - * {@link ServletContext} from registry, or if it {@link ServletContext} isn't - * registered, adds it to the registry with empty - * {@link ServletContextDescriptor} + * This method retrieves {@link ServletContextDescriptor} for a {@link ServletContext} from registry, or if it + * {@link ServletContext} isn't registered, adds it to the registry with empty {@link ServletContextDescriptor} * * @param servletContext * the active servlet context @@ -547,11 +530,10 @@ private ServletContextDescriptor getDescriptor(ServletContext servletContext) { } /** - * This method is used by injected code to register listeners for - * {@link ServletContext}. If object argument is a {@link ServletContext} and - * listener argument contains {@link HttpSessionListener} or - * {@link HttpSessionAttributeListener}, the method will add them to list of - * known listeners associated to {@link ServletContext} + * This method is used by injected code to register listeners for {@link ServletContext}. If object argument is a + * {@link ServletContext} and listener argument contains {@link HttpSessionListener} or + * {@link HttpSessionAttributeListener}, the method will add them to list of known listeners associated to + * {@link ServletContext} * * @param servletContext * the active servlet context @@ -580,8 +562,7 @@ public void onAddListener(ServletContext servletContext, Object listener) { } /** - * Sets up servlet context - registers {@link SessionFilter} and - * {@link ShutdownListener}. + * Sets up servlet context - registers {@link SessionFilter} and {@link ShutdownListener}. * * @param context * servlet context to set up diff --git a/session-replacement/src/main/java/com/amadeus/session/servlet/SessionHelpersFacade.java b/session-replacement/src/main/java/com/amadeus/session/servlet/SessionHelpersFacade.java index 18e06a6..6dc6a60 100644 --- a/session-replacement/src/main/java/com/amadeus/session/servlet/SessionHelpersFacade.java +++ b/session-replacement/src/main/java/com/amadeus/session/servlet/SessionHelpersFacade.java @@ -16,8 +16,8 @@ import org.slf4j.LoggerFactory; /** - * This class contains various methods that are called either from session - * enabled filters, or from code injected by SessionAgent. + * This class contains various methods that are called either from session enabled filters, or from code injected by + * SessionAgent. */ public final class SessionHelpersFacade { @@ -31,12 +31,10 @@ private SessionHelpersFacade() { } /** - * This method is called from {@link SessionFilter} or from {@link Filter} - * implementations modified by SessionAgent. The method wraps - * {@link ServletRequest} in {@link HttpRequestWrapper}. + * This method is called from {@link SessionFilter} or from {@link Filter} implementations modified by SessionAgent. + * The method wraps {@link ServletRequest} in {@link HttpRequestWrapper}. *

- * The method will wrap request at most once per request and will only wrap - * instances of {@link HttpServletRequest}. + * The method will wrap request at most once per request and will only wrap instances of {@link HttpServletRequest}. * * @param request * request received by filter @@ -60,9 +58,8 @@ private static ServletContext context(ServletRequest request, ServletContext con } /** - * This method is called from {@link SessionFilter} or from {@link Filter} - * implementations modified by SessionAgent. The method retrieves response - * stored in {@link HttpRequestWrapper}. + * This method is called from {@link SessionFilter} or from {@link Filter} implementations modified by SessionAgent. + * The method retrieves response stored in {@link HttpRequestWrapper}. * * @param request * request received by filter @@ -78,8 +75,7 @@ public static ServletResponse prepareResponse(ServletRequest request, ServletRes } /** - * This method initializes session management for a given - * {@link ServletContext}. This method is called from + * This method initializes session management for a given {@link ServletContext}. This method is called from * {@link SessionFilter#init(javax.servlet.FilterConfig)}. * * @param reset @@ -88,13 +84,12 @@ public static ServletResponse prepareResponse(ServletRequest request, ServletRes * the servlet context where filter is registered * */ - public static void initSessionManagementReset(ServletContext servletContext,boolean reset) { - helpers(servletContext).initSessionManagement(servletContext,reset); + public static void initSessionManagementReset(ServletContext servletContext, boolean reset) { + helpers(servletContext).initSessionManagement(servletContext, reset); } /** - * This method initializes session management for a given - * {@link ServletContext}. This method is called from + * This method initializes session management for a given {@link ServletContext}. This method is called from * {@link SessionFilter#init(javax.servlet.FilterConfig)}. * * @param servletContext @@ -102,17 +97,15 @@ public static void initSessionManagementReset(ServletContext servletContext,bool * */ public static void initSessionManagement(ServletContext servletContext) { - helpers(servletContext).initSessionManagement(servletContext,false); - } - + helpers(servletContext).initSessionManagement(servletContext, false); + } + /** - * Commits request and stores session in repository. This method is called - * from the filter. The commit is only done if the filter is the one that - * wrapped the request into HttpRequestWrapper. + * Commits request and stores session in repository. This method is called from the filter. The commit is only done if + * the filter is the one that wrapped the request into HttpRequestWrapper. *

- * The logic to check if the caller filter is the one that wrapped request is - * based on requirement that original request and the one used by filter are - * different and that original request is not {@link HttpRequestWrapper}. + * The logic to check if the caller filter is the one that wrapped request is based on requirement that original + * request and the one used by filter are different and that original request is not {@link HttpRequestWrapper}. * * @param request * potentially wrapped request @@ -120,16 +113,18 @@ public static void initSessionManagement(ServletContext servletContext) { * original request received by filter * @param filterContext * servlet context of the filter + * @throws IOException + * exception when connection redis failed */ - public static void commitRequest(ServletRequest request, ServletRequest oldRequest, ServletContext filterContext) throws IOException { + public static void commitRequest(ServletRequest request, ServletRequest oldRequest, ServletContext filterContext) + throws IOException { helpers(context(request, filterContext)).commitRequest(request, oldRequest); } /** - * Call to this method is injected by agent into implementations of - * {@link HttpSessionAttributeListener} and {@link HttpSessionListener} inside - * Servlet 2.5 containers. It's roll is to collect session listeners so they - * can be invoked by the library when it manages sessions. + * Call to this method is injected by agent into implementations of {@link HttpSessionAttributeListener} and + * {@link HttpSessionListener} inside Servlet 2.5 containers. It's roll is to collect session listeners so they can be + * invoked by the library when it manages sessions. * * @param listener * listener where event was received @@ -145,11 +140,10 @@ public static void interceptHttpListener(Object listener, HttpSessionEvent event } /** - * This method is used by injected code to register listeners for - * {@link ServletContext}. If object argument is a {@link ServletContext} and - * listener argument contains {@link HttpSessionListener} or - * {@link HttpSessionAttributeListener}, the method will add them to list of - * known listeners associated to {@link ServletContext} + * This method is used by injected code to register listeners for {@link ServletContext}. If object argument is a + * {@link ServletContext} and listener argument contains {@link HttpSessionListener} or + * {@link HttpSessionAttributeListener}, the method will add them to list of known listeners associated to + * {@link ServletContext} * * @param object * the object that should be servlet context @@ -166,8 +160,7 @@ public static void onAddListener(Object object, Object listener) { } /** - * This method retrieves or creates session helpers associated to servlet - * context {@link SessionHelpers}. + * This method retrieves or creates session helpers associated to servlet context {@link SessionHelpers}. * * @param servletContext * the active servlet context From 48b0fff5868c302857123acea0bcd834cc0b75de Mon Sep 17 00:00:00 2001 From: Nenad Bogojevic Date: Wed, 6 Jun 2018 10:44:29 +0200 Subject: [PATCH 2/8] Update SessionFilter.java --- .../java/com/amadeus/session/servlet/SessionFilter.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/session-replacement/src/main/java/com/amadeus/session/servlet/SessionFilter.java b/session-replacement/src/main/java/com/amadeus/session/servlet/SessionFilter.java index 3aac63f..188e5fa 100644 --- a/session-replacement/src/main/java/com/amadeus/session/servlet/SessionFilter.java +++ b/session-replacement/src/main/java/com/amadeus/session/servlet/SessionFilter.java @@ -97,7 +97,6 @@ public void doFilter(ServletRequest originalRequest, ServletResponse originalRes throw e; } } - } private void ext(SessionManager sessionManager, Exception e) { @@ -114,27 +113,20 @@ private void ext(SessionManager sessionManager, Exception e) { boolean lock = resetManager.tryLock(); if (lock) { try { - if (sessionManagercurrent != null) { sessionManagercurrent.reset(); } initSessionManagementReset(servletContext, true); - } finally { resetManager.unlock(); } - } else { logger.warn("already lokked"); } } else { logger.warn("Error into redis but the limits is not reach:" + errorTracker.size()); } - - } else { - } - } } From fb3081e0e1f63c4b172b170320f5e92404f5b876 Mon Sep 17 00:00:00 2001 From: Nenad Bogojevic Date: Wed, 6 Jun 2018 10:46:08 +0200 Subject: [PATCH 3/8] Update ErrorTracker.java --- .../main/java/com/amadeus/session/ErrorTracker.java | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/session-replacement/src/main/java/com/amadeus/session/ErrorTracker.java b/session-replacement/src/main/java/com/amadeus/session/ErrorTracker.java index 796e4f3..7074017 100644 --- a/session-replacement/src/main/java/com/amadeus/session/ErrorTracker.java +++ b/session-replacement/src/main/java/com/amadeus/session/ErrorTracker.java @@ -8,15 +8,8 @@ /** * The class is used to determine if the application is in error or not * - * If the number of error stored during the delay reach the max , the application is in error - * - * period - * - * Time in milliseconds while items are kept - * - * max - * - * If the number of items is more than the max value the Tracker is considered in error + * If the number of error stored during the delay reach the max, the application is in error + * period. * */ From 8ebf05f7d2c8b39892609a739b389e8570c69238 Mon Sep 17 00:00:00 2001 From: Nenad Bogojevic Date: Wed, 6 Jun 2018 10:47:39 +0200 Subject: [PATCH 4/8] Update ErrorTracker.java --- .../main/java/com/amadeus/session/ErrorTracker.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/session-replacement/src/main/java/com/amadeus/session/ErrorTracker.java b/session-replacement/src/main/java/com/amadeus/session/ErrorTracker.java index 7074017..0bd61e5 100644 --- a/session-replacement/src/main/java/com/amadeus/session/ErrorTracker.java +++ b/session-replacement/src/main/java/com/amadeus/session/ErrorTracker.java @@ -42,14 +42,12 @@ public ErrorTracker(int period, int max) { final int max; /** - * The parameter is a time with the format millisecond from 1900 ( System.currentTimeMillis() ) This method add an - * event into the Tracker and remove all the old event with the followinf criteria - * - * now - oldevent superior to period will be - * - * removed + * The parameter is a time with the format millisecond from 1900 ( System.currentTimeMillis() ). This method add an + * event into the Tracker and remove all the old event with the following criteria: + * now - oldevent superior to period will be removed * * @param now + * oldevent superior to period will be */ public void addError(long now) { From 570a7bd28fca1a8a35aa9d03effa908d903196be Mon Sep 17 00:00:00 2001 From: Nenad Bogojevic Date: Wed, 6 Jun 2018 10:47:59 +0200 Subject: [PATCH 5/8] Update ErrorTracker.java --- .../src/main/java/com/amadeus/session/ErrorTracker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/session-replacement/src/main/java/com/amadeus/session/ErrorTracker.java b/session-replacement/src/main/java/com/amadeus/session/ErrorTracker.java index 0bd61e5..1d25971 100644 --- a/session-replacement/src/main/java/com/amadeus/session/ErrorTracker.java +++ b/session-replacement/src/main/java/com/amadeus/session/ErrorTracker.java @@ -47,7 +47,7 @@ public ErrorTracker(int period, int max) { * now - oldevent superior to period will be removed * * @param now - * oldevent superior to period will be + * current instance */ public void addError(long now) { From 21b33f23b200c5b9d619bcc33c9266a6ebca10ff Mon Sep 17 00:00:00 2001 From: vdoleans Date: Tue, 17 Jul 2018 16:20:55 +0200 Subject: [PATCH 6/8] Reset of scheduler --- .../com/amadeus/session/ExecutorFacade.java | 61 +-- .../amadeus/session/SessionConfiguration.java | 376 +++++++++--------- .../com/amadeus/session/SessionManager.java | 10 + .../repository/redis/RedisConfiguration.java | 88 ++-- .../session/servlet/SessionFilter.java | 33 +- .../session/servlet/SessionHelpers.java | 36 +- 6 files changed, 330 insertions(+), 274 deletions(-) diff --git a/session-replacement/src/main/java/com/amadeus/session/ExecutorFacade.java b/session-replacement/src/main/java/com/amadeus/session/ExecutorFacade.java index 1ff1e97..b14b4ee 100644 --- a/session-replacement/src/main/java/com/amadeus/session/ExecutorFacade.java +++ b/session-replacement/src/main/java/com/amadeus/session/ExecutorFacade.java @@ -26,33 +26,42 @@ import com.codahale.metrics.MetricRegistry; /** - * Support class that provides methods for launching and scheduling of tasks. - * The implementation will use either managed thread factory when supported by - * JEE container, or {@link Executors#defaultThreadFactory()} if the managed one - * was not available. + * Support class that provides methods for launching and scheduling of tasks. The implementation will use either managed + * thread factory when supported by JEE container, or {@link Executors#defaultThreadFactory()} if the managed one was + * not available. *

- * The implementation also provides metrics about number of thread in pool and - * number of active threads. + * The implementation also provides metrics about number of thread in pool and number of active threads. *

*/ public class ExecutorFacade implements UncaughtExceptionHandler, ThreadFactory { private static final Logger logger = LoggerFactory.getLogger(ExecutorFacade.class); private static final String THREAD_JNDI = "com.amadeus.session.thread.jndi"; + private static final String WORK_QUEUE_SIZE = "com.amadeus.session.thread.queue"; + private static final String METRIC_PREFIX = "com.amadeus.session"; private static final int WAIT_FOR_SHUTDOWN = 10; + private static final int CORE_THREADS_IN_POOL = 4; + private static final int SCHEDULER_THREADS_IN_POOL = 2; + private static final int THREAD_KEEPALIVE_TIME = 10; + private static final int MAXIMUM_THREADS_IN_POOL = 40; + private static final String MAXIMUM_WORK_QUEUE_SIZE = String.valueOf(100); private final ThreadPoolExecutor executor; + private final ScheduledThreadPoolExecutor scheduledExecutor; + private final ThreadFactory baseThreadFactory; + private final String namespace; + private final AtomicLong count; /** @@ -85,8 +94,7 @@ public ExecutorFacade(SessionConfiguration conf) { } /** - * This method creates new thread from pool and add namespace to the thread - * name. + * This method creates new thread from pool and add namespace to the thread name. */ @Override public Thread newThread(Runnable r) { @@ -97,9 +105,8 @@ public Thread newThread(Runnable r) { } /** - * Submits a Runnable task for execution and returns a Future representing - * that task. The Future's {@code get} method will return {@code null} upon - * successful completion. + * Submits a Runnable task for execution and returns a Future representing that task. The Future's {@code get} method + * will return {@code null} upon successful completion. * * @param task * the task to submit @@ -114,15 +121,12 @@ public Future submit(Runnable task) { } /** - * Creates and executes a periodic action that becomes enabled first after the - * given initial delay, and subsequently with the given period; that is - * executions will commence after {@code initialDelay} then - * {@code initialDelay+period}, then {@code initialDelay + 2 * period}, and so - * on. If any execution of the task encounters an exception, subsequent - * executions are suppressed. Otherwise, the task will only terminate via - * cancellation or termination of the executor. If any execution of this task - * takes longer than its period, then subsequent executions may start late, - * but will not concurrently execute. + * Creates and executes a periodic action that becomes enabled first after the given initial delay, and subsequently + * with the given period; that is executions will commence after {@code initialDelay} then + * {@code initialDelay+period}, then {@code initialDelay + 2 * period}, and so on. If any execution of the task + * encounters an exception, subsequent executions are suppressed. Otherwise, the task will only terminate via + * cancellation or termination of the executor. If any execution of this task takes longer than its period, then + * subsequent executions may start late, but will not concurrently execute. * * @param task * the task to execute @@ -132,9 +136,8 @@ public Future submit(Runnable task) { * the period between successive executions * @param unit * the time unit of the initialDelay and period parameters - * @return a ScheduledFuture representing pending completion of the task, and - * whose {@code get()} method will throw an exception upon - * cancellation + * @return a ScheduledFuture representing pending completion of the task, and whose {@code get()} method will throw an + * exception upon cancellation * @throws RejectedExecutionException * if the task cannot be scheduled for execution * @throws NullPointerException @@ -164,8 +167,7 @@ public Long getValue() { } /** - * Registers monitoring for {@link ThreadPoolExecutor} using passed - * {@link MetricRegistry}. + * Registers monitoring for {@link ThreadPoolExecutor} using passed {@link MetricRegistry}. * * @param name * the prefix for the metrics @@ -203,8 +205,8 @@ public Integer getValue() { } /** - * Helper class that is used to discard tasks for which there are no free - * threads. The implementation will simply log this occurrence. + * Helper class that is used to discard tasks for which there are no free threads. The implementation will simply log + * this occurrence. */ static class DiscardAndLog implements RejectedExecutionHandler { @@ -215,8 +217,7 @@ public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { } /** - * The method will log uncaught exceptions that occurred during thread - * execution. + * The method will log uncaught exceptions that occurred during thread execution. */ @Override public void uncaughtException(Thread t, Throwable e) { @@ -232,7 +233,9 @@ public void uncaughtException(Thread t, Throwable e) { public void shutdown() { logger.info("Shutting down the executor."); executor.shutdown(); + executor.shutdownNow(); scheduledExecutor.shutdown(); + scheduledExecutor.shutdownNow(); try { executor.awaitTermination(WAIT_FOR_SHUTDOWN, SECONDS); scheduledExecutor.awaitTermination(WAIT_FOR_SHUTDOWN, SECONDS); diff --git a/session-replacement/src/main/java/com/amadeus/session/SessionConfiguration.java b/session-replacement/src/main/java/com/amadeus/session/SessionConfiguration.java index 519be14..a089a33 100644 --- a/session-replacement/src/main/java/com/amadeus/session/SessionConfiguration.java +++ b/session-replacement/src/main/java/com/amadeus/session/SessionConfiguration.java @@ -18,33 +18,31 @@ import org.slf4j.LoggerFactory; /** - * Main configuration parameters for the session management. This includes - * information if session can be distributed and default timeout. + * Main configuration parameters for the session management. This includes information if session can be distributed and + * default timeout. *

* The parameters are configured using following system properties: *

- * com.amadeus.session.distributable set to true enables session to - * be stored in distributed storage. + * com.amadeus.session.distributable set to true enables session to be stored in distributed storage. *

- * com.amadeus.session.timeout specifies default session inactivity - * timeout in seconds. Default value is 1800 seconds. + * com.amadeus.session.timeout specifies default session inactivity timeout in seconds. Default value is + * 1800 seconds. *

- * com.amadeus.session.non-cachable specifies comma-separated list - * of session attributes that must be synchronized with repository. By default, - * this list is empty. com.amadeus.session.replication-trigger - * specifies repository behavior when accessing attributes. See - * {@link ReplicationTrigger} enumeration for details. Default value is - * {@link ReplicationTrigger#SET_AND_NON_PRIMITIVE_GET}. + * com.amadeus.session.non-cachable specifies comma-separated list of session attributes that must be + * synchronized with repository. By default, this list is empty. com.amadeus.session.replication-trigger + * specifies repository behavior when accessing attributes. See {@link ReplicationTrigger} enumeration for details. + * Default value is {@link ReplicationTrigger#SET_AND_NON_PRIMITIVE_GET}. *

- * com.amadeus.session.logging.mdc.enabled activates adding current - * session id to logging systems Mapped Diagnostic Context (MDC). + * com.amadeus.session.logging.mdc.enabled activates adding current session id to logging systems Mapped + * Diagnostic Context (MDC). *

- * com.amadeus.session.logging.mdc.name specifies key used to store - * current session id to logging systems Mapped Diagnostic Context (MDC). + * com.amadeus.session.logging.mdc.name specifies key used to store current session id to logging systems + * Mapped Diagnostic Context (MDC). * */ public class SessionConfiguration implements Serializable { private static final long serialVersionUID = -4538053252686416412L; + private static final Logger logger = LoggerFactory.getLogger(SessionConfiguration.class); /** @@ -52,20 +50,16 @@ public class SessionConfiguration implements Serializable { */ public enum ReplicationTrigger { /** - * Session data is replicated on set of the attribute and when an attribute - * retrieved via Attribute contains a non-primitive type. This means that - * the get of an attribute of the well-known Java type such as Boolean, - * Character, Number (Double, Float, Integer, Long), doesn't trigger - * replication to repository, but getAttribute operation for other types of - * attribute will trigger update in the repository. + * Session data is replicated on set of the attribute and when an attribute retrieved via Attribute contains a + * non-primitive type. This means that the get of an attribute of the well-known Java type such as Boolean, + * Character, Number (Double, Float, Integer, Long), doesn't trigger replication to repository, but getAttribute + * operation for other types of attribute will trigger update in the repository. */ SET_AND_NON_PRIMITIVE_GET(true), /** - * This option assumes that the application will explicitly call - * setAttribute on the session when the data needs to be replicated. It - * prevents unnecessary replication and can benefit overall performance, but - * is inherently unsafe as attributes that were changed after the get, but - * where never + * This option assumes that the application will explicitly call setAttribute on the session when the data needs to + * be replicated. It prevents unnecessary replication and can benefit overall performance, but is inherently unsafe + * as attributes that were changed after the get, but where never */ SET(false); @@ -76,8 +70,7 @@ private ReplicationTrigger(boolean replicateOnTrigger) { } /** - * Returns true if session should be replicated on getAttribute - * operation + * Returns true if session should be replicated on getAttribute operation * * @return true if session should be replicated on get */ @@ -86,8 +79,8 @@ public boolean isReplicateOnGet() { } /** - * Checks passed value against allowed values in enumeration. If it is not - * valid, returns default value and logs error. + * Checks passed value against allowed values in enumeration. If it is not valid, returns default value and logs + * error. * * @param replicationValue * value to check @@ -108,8 +101,7 @@ public static ReplicationTrigger validate(String replicationValue) { } /** - * Attribute provider can be used via call to - * {@link SessionConfiguration#initializeFrom(AttributeProvider)} to set up + * Attribute provider can be used via call to {@link SessionConfiguration#initializeFrom(AttributeProvider)} to set up * SessionConfiguration. */ public interface AttributeProvider { @@ -130,45 +122,45 @@ public interface AttributeProvider { Object source(); } - - - - - /** * Indicates the interval when error are count. */ public static final int DEFAULT_TRACKER_ERROR_INTERVAL_MILLISECONDS_NUM = 60000; - public static final String TRACKER_ERROR_INTERVAL_MILLISECONDS_KEY = "com.amadeus.session.tracker.interval" ; + + public static final String TRACKER_ERROR_INTERVAL_MILLISECONDS_KEY = "com.amadeus.session.tracker.interval"; + /** * Indicates the maximun number of errors before request the reset of redis connection. */ public static final int DEFAULT_TRACKER_ERROR_LIMITS_NUMBER = 50; - public static final String TRACKER_ERROR_LIMITS_NUMBER_KEY = "com.amadeus.session.tracker.limits" ; - + + public static final String TRACKER_ERROR_LIMITS_NUMBER_KEY = "com.amadeus.session.tracker.limits"; + /** * Indicates if sessions can be distributed or not. */ public static final String DISTRIBUTABLE_SESSION = "com.amadeus.session.distributable"; + /** - * Non-distributable web apps will be treated as distributable if this - * parameter is set to true. + * Non-distributable web apps will be treated as distributable if this parameter is set to true. */ public static final String FORCE_DISTRIBUTABLE = "com.amadeus.session.distributable.force"; + /** * Default session timeout in seconds. */ public static final String DEFAULT_SESSION_TIMEOUT = "com.amadeus.session.timeout"; + /** - * List of attributes that must be retrieved from repository (i.e. they can't - * be cached locally). + * List of attributes that must be retrieved from repository (i.e. they can't be cached locally). */ public static final String NON_CACHEABLE_ATTRIBUTES = "com.amadeus.session.non-cacheable"; + /** - * Strategy for for triggering replication. See {@link ReplicationTrigger} - * enumeration. + * Strategy for for triggering replication. See {@link ReplicationTrigger} enumeration. */ public static final String SESSION_REPLICATION_TRIGGER = "com.amadeus.session.replication-trigger"; + /** * Default strategy for detecting that attribute changed. */ @@ -178,35 +170,36 @@ public interface AttributeProvider { * Is session id stored in logging MDC. */ public static final String LOG_MDC_SESSION_ENABLED = "com.amadeus.session.logging.mdc.enabled"; + /** * The name of the logging MDC attribute where session id is stored. */ public static final String LOG_MDC_SESSION_NAME = "com.amadeus.session.logging.mdc.name"; + /** * Default key used to store session id in logging system's MDC. */ public static final String LOGGING_MDC_DEFAULT_KEY = "JSESSIONID"; /** - * Activates sticky session strategy. When activated, implementation should - * try to handle all session activity on the last node that processed client - * request that impacts the session. + * Activates sticky session strategy. When activated, implementation should try to handle all session activity on the + * last node that processed client request that impacts the session. */ public static final String STICKY_SESSIONS = "com.amadeus.session.sticky"; + /** * By default, sessions are sticky. */ public static final String DEFAULT_STICKY_SESSIONS = "true"; /** - * The namespace for sessions. It is best practice to have sessions in - * different applications or webapps should having different namespaces. If - * applications want to share sessions, then they can use same namespace. In - * case of webapps, namespace can be defined using servlet init parameter, or - * if not present, the context name of the webapp is used as namespace. + * The namespace for sessions. It is best practice to have sessions in different applications or webapps should having + * different namespaces. If applications want to share sessions, then they can use same namespace. In case of webapps, + * namespace can be defined using servlet init parameter, or if not present, the context name of the webapp is used as + * namespace. */ public static final String SESSION_NAMESPACE = "com.amadeus.session.namespace"; - + /** * Default session namespace is default */ @@ -216,46 +209,48 @@ public interface AttributeProvider { * Indicate if generated session prefixed with!Timestamp. */ public static final String SESSION_TIMESTAMP = "com.amadeus.session.timestamp"; - + /** * Default session timestamp is false */ public static final String DEFAULT_SESSION_TIMESTAMP = "false"; - + /** * Default session timeout is 30 minutes. */ public static final int DEFAULT_SESSION_TIMEOUT_VALUE_NUM = 1800; + // String version of default session timeout private static final String DEFAULT_SESSION_TIMEOUT_VALUE = String.valueOf(DEFAULT_SESSION_TIMEOUT_VALUE_NUM); /** - * Enables overriding the name of the host. By default it is retrieved from - * environment. See {@link #initNode()} for details. + * Enables overriding the name of the host. By default it is retrieved from environment. See {@link #initNode()} for + * details. */ public static final String SESSION_HOST = "com.amadeus.session.host"; + /** - * ServletContext parameter or system property containing the configuration - * for the {@link SessionRepository}. See each implementation for detailed - * format. By convention, items in the format are separated by commas. + * ServletContext parameter or system property containing the configuration for the {@link SessionRepository}. See + * each implementation for detailed format. By convention, items in the format are separated by commas. */ public static final String PROVIDER_CONFIGURATION = "com.amadeus.session.repository.conf"; + /** - * ServletContext parameter or system property containing the name of - * {@link SessionRepositoryFactory} implementation. The value is either name - * of the class or registered repository name such as redis, + * ServletContext parameter or system property containing the name of {@link SessionRepositoryFactory} implementation. + * The value is either name of the class or registered repository name such as redis, * in-memory */ public static final String REPOSITORY_FACTORY_NAME = "com.amadeus.session.repository.factory"; + /** - * ServletContext parameter or system property containing comma delimited list - * of the names of {@link SessionTracking} implementations or values from - * com.amadeus.session.servlet.SessionPropagation enumeration. + * ServletContext parameter or system property containing comma delimited list of the names of {@link SessionTracking} + * implementations or values from com.amadeus.session.servlet.SessionPropagation enumeration. */ public static final String SESSION_PROPAGATOR_NAME = "com.amadeus.session.tracking"; + /** - * ServletContext parameter or system property containing the name of the - * cookie or URL element for propagating session. + * ServletContext parameter or system property containing the name of the cookie or URL element for propagating + * session. * * @see #DEFAULT_SESSION_ID_NAME */ @@ -277,19 +272,20 @@ public interface AttributeProvider { * ServletContext parameter or system property disabled session management. */ public static final String DISABLED_SESSION = "com.amadeus.session.disabled"; + /** - * ServletContext parameter or system property activating sharing of instances - * of session during concurrent requests. + * ServletContext parameter or system property activating sharing of instances of session during concurrent requests. */ public static final String REUSE_CONCURRENT_SESSION = "com.amadeus.session.reuse.concurrent"; + /** - * ServletContext parameter or system property indicating what provider - * generates session ids. + * ServletContext parameter or system property indicating what provider generates session ids. */ public static final String SESSION_ID_PROVIDER = "com.amadeus.session.id"; + /** - * ServletContext parameter or system property specifying the length of the - * generates session ids. Used in {@link RandomIdProvider}. + * ServletContext parameter or system property specifying the length of the generates session ids. Used in + * {@link RandomIdProvider}. */ public static final String SESSION_ID_LENGTH = "com.amadeus.session.id.length"; @@ -299,20 +295,21 @@ public interface AttributeProvider { public static final String DEFAULT_SESSION_ID_LENGTH = "30"; /** - * Specifies if listeners should be discovered using interception of native - * session. + * Specifies if listeners should be discovered using interception of native session. */ public static final String INTERCEPT_LISTENERS = "com.amadeus.session.intercept.listeners"; + /** * Specifies if commit should be done on all concurrent requests to session. */ public static final String COMMIT_ON_ALL_CONCURRENT = "com.amadeus.session.commit.concurrent"; + /** - * Specifies key to be used for encryption. When present activates encryption - * automatically. If key specifies a URL, key will be loaded from specified - * address. Otherwise it is treated literally. + * Specifies key to be used for encryption. When present activates encryption automatically. If key specifies a URL, + * key will be loaded from specified address. Otherwise it is treated literally. */ public static final String SESSION_ENCRYPTION_KEY = "com.amadeus.session.encryption.key"; + /** * Set to true if session should delegate PrintWriter implementation to container. By default it is * false and session replacer provides it's own implementation. @@ -320,30 +317,53 @@ public interface AttributeProvider { public static final String DELEGATE_WRITER = "com.amadeus.session.delegate.writer"; private int trackerInterval; + private int trackerLimits; + private int maxInactiveInterval; + private boolean distributable; + private boolean sticky; + private boolean timestampSufix; + private boolean allowedCachedSessionReuse; + private boolean interceptListeners; + private boolean forceDistributable; + private boolean loggingMdcActive; + private boolean usingEncryption; + private String loggingMdcKey; + private String node; + private String namespace; + private String providerConfiguration; + private String repositoryFactory; + private String[] sessionTracking; + private String sessionIdName; + private String encryptionKey; private Set nonCacheable; + private ReplicationTrigger replicationTrigger; + private Properties attributes; + private transient AttributeProvider currentAttributeProvider; + private boolean commitOnAllConcurrent; + private boolean delegateWriter; /** @@ -380,38 +400,37 @@ public SessionConfiguration() { logger.error("`{}` system property was not an integer: {}, using default {}", DEFAULT_SESSION_TIMEOUT, inactiveValue, maxInactiveInterval); } - - trackerInterval = init(TRACKER_ERROR_INTERVAL_MILLISECONDS_KEY,DEFAULT_TRACKER_ERROR_INTERVAL_MILLISECONDS_NUM); - trackerLimits = init(TRACKER_ERROR_LIMITS_NUMBER_KEY,DEFAULT_TRACKER_ERROR_LIMITS_NUMBER); - logger.error("trackerInterval:" + trackerInterval ); - logger.error("trackerLimits :" + trackerLimits ); - - + + trackerInterval = init(TRACKER_ERROR_INTERVAL_MILLISECONDS_KEY, DEFAULT_TRACKER_ERROR_INTERVAL_MILLISECONDS_NUM); + trackerLimits = init(TRACKER_ERROR_LIMITS_NUMBER_KEY, DEFAULT_TRACKER_ERROR_LIMITS_NUMBER); + logger.info("trackerInterval:" + trackerInterval); + logger.info("trackerLimits :" + trackerLimits); + node = initNode(); setEncryptionKey(getPropertySecured(SESSION_ENCRYPTION_KEY, null)); } - private int init( String key , int def) { + private int init(String key, int def) { int intVal = def; - String strVal = getPropertySecured(key , String.valueOf(def)); + String strVal = getPropertySecured(key, String.valueOf(def)); try { if (nonEmpty(strVal)) { intVal = Integer.parseInt(strVal); } } catch (NumberFormatException e) { - logger.error("`{}` system property was not an integer: {}, using default {}", key, - strVal, intVal); + logger.error("`{}` system property was not an integer: {}, using default {}", key, strVal, intVal); } - return intVal ; + return intVal; } /** - * Parses value as comma-separated list of session propagators. Used to - * specify several propagator in order of priority. + * Parses value as comma-separated list of session propagators. Used to specify several propagator in order of + * priority. + * * @param value * the value to parse - * @param defaultValue - * the default value if value is null + * @param defaultValue + * the default value if value is null */ private String[] parsePropagators(String value, String[] defaultValue) { if (value == null) { @@ -421,8 +440,7 @@ private String[] parsePropagators(String value, String[] defaultValue) { } /** - * Sets encryption key to use. If key is null, encryption is - * deactivated. + * Sets encryption key to use. If key is null, encryption is deactivated. * * @param key * encryption key to use or null @@ -437,9 +455,8 @@ static boolean allowedProtocol(String protocol) { } /** - * Allows setting up configuration from external source. It is expected that - * external source offers the same attributes as the ones read from system - * properties. + * Allows setting up configuration from external source. It is expected that external source offers the same + * attributes as the ones read from system properties. * * @param provider * the external source for attributes @@ -474,26 +491,25 @@ public void initializeFrom(AttributeProvider provider) { if (nonEmpty(value)) { setNonCacheable(value); } - maxInactiveInterval = initInt(provider,DEFAULT_SESSION_TIMEOUT,maxInactiveInterval); - trackerLimits = initInt(provider,TRACKER_ERROR_LIMITS_NUMBER_KEY ,trackerLimits); - trackerInterval = initInt(provider,TRACKER_ERROR_INTERVAL_MILLISECONDS_KEY,trackerInterval); - - logger.error("trackerInterval:" + trackerInterval ); - logger.error("trackerLimits :" + trackerLimits ); - + maxInactiveInterval = initInt(provider, DEFAULT_SESSION_TIMEOUT, maxInactiveInterval); + trackerLimits = initInt(provider, TRACKER_ERROR_LIMITS_NUMBER_KEY, trackerLimits); + trackerInterval = initInt(provider, TRACKER_ERROR_INTERVAL_MILLISECONDS_KEY, trackerInterval); + + logger.info("trackerInterval:" + trackerInterval); + logger.info("trackerLimits :" + trackerLimits); + } - private int initInt(AttributeProvider provider , String name , int maxInactiveInterval) { + private int initInt(AttributeProvider provider, String name, int maxInactiveInterval) { String val = provider.getAttribute(name); if (nonEmpty(val)) { try { return Integer.parseInt(val); } catch (NumberFormatException e) { - logger.warn("`{}` configuration attribute was not an integer: {} for source {}", name, val, - provider.source()); + logger.warn("`{}` configuration attribute was not an integer: {} for source {}", name, val, provider.source()); } } - return maxInactiveInterval; + return maxInactiveInterval; } private boolean read(String key, boolean defaultValue) { @@ -574,8 +590,8 @@ public void setNonCacheable(Set nonCacheable) { } /** - * Sets set of keys that should not be cached locally by extracting keys from - * comma-separated list provided as parameter. + * Sets set of keys that should not be cached locally by extracting keys from comma-separated list provided as + * parameter. * * @param nonCacheableAttributesCsv * list of non cacheable attributes in comma-separated list @@ -607,8 +623,8 @@ public void setReplicationTrigger(ReplicationTrigger replicationTrigger) { } /** - * Returns true if session information should be stored in - * logging systems Mapped Diagnostic Context (MDC). + * Returns true if session information should be stored in logging systems Mapped Diagnostic Context + * (MDC). * * @return true if session information should be stored in MDC */ @@ -617,8 +633,7 @@ public boolean isLoggingMdcActive() { } /** - * Sets whether session information should be stored in logging systems Mapped - * Diagnostic Context (MDC). + * Sets whether session information should be stored in logging systems Mapped Diagnostic Context (MDC). * * @param loggingMdcActive * true if logging should add information to MDC @@ -628,8 +643,7 @@ public void setLoggingMdcActive(boolean loggingMdcActive) { } /** - * Returns key used to store current session id to logging system's Mapped - * Diagnostic Context (MDC). + * Returns key used to store current session id to logging system's Mapped Diagnostic Context (MDC). * * @return the key used for session id during logging */ @@ -638,20 +652,18 @@ public String getLoggingMdcKey() { } /** - * Sets key used to store current session id to logging system's Mapped - * Diagnostic Context (MDC). + * Sets key used to store current session id to logging system's Mapped Diagnostic Context (MDC). * * @param loggingMdcKey - * the key value to use. If value is null, - * {@link #LOGGING_MDC_DEFAULT_KEY} is used as key + * the key value to use. If value is null, {@link #LOGGING_MDC_DEFAULT_KEY} is used as key */ public void setLoggingMdcKey(String loggingMdcKey) { this.loggingMdcKey = loggingMdcKey; } /** - * Returns true if sessions are sticky. Sticky sessions should be - * expired on the last node that used them. + * Returns true if sessions are sticky. Sticky sessions should be expired on the last node that used + * them. * * @return true if session is sticky */ @@ -687,7 +699,7 @@ public boolean isTimestampSufix() { public void setTimestampSufix(boolean timestamp) { this.timestampSufix = timestamp; } - + /** * Returns id of the current node * @@ -708,8 +720,7 @@ public void setNode(String node) { } /** - * Namespace for session. It will never be null (if null, value - * default). + * Namespace for session. It will never be null (if null, value default). * * @return namespace for session */ @@ -775,9 +786,8 @@ public void setRepositoryFactory(String repositoryFactory) { } /** - * Returns class name or unique id of the session tracking. - * {@link SessionTracking} is the class responsible for reading and - * propagating session id. + * Returns class name or unique id of the session tracking. {@link SessionTracking} is the class responsible for + * reading and propagating session id. * * @return the name of the session tracking class */ @@ -786,19 +796,18 @@ public String[] getSessionTracking() { } /** - * Sets class name or unique id of the session tracking. See - * {@link #getSessionTracking()}. + * Sets class name or unique id of the session tracking. See {@link #getSessionTracking()}. * * @param sessionTracking * the unique id or name of the session tracking class */ - public void setSessionTracking(String...sessionTracking) { + public void setSessionTracking(String... sessionTracking) { this.sessionTracking = sessionTracking; } /** - * Returns name of identifier that is used to stored session id. E.g. this - * will be cookie name if session uses cookie propagation. + * Returns name of identifier that is used to stored session id. E.g. this will be cookie name if session uses cookie + * propagation. * * @return the session identifier */ @@ -817,8 +826,8 @@ public void setSessionIdName(String sessionIdName) { } /** - * Returns true if multiple concurrent threads that operate on - * same session can re-use session from local cache. + * Returns true if multiple concurrent threads that operate on same session can re-use session from local + * cache. * * @return true if concurrent threads can access same session */ @@ -827,8 +836,7 @@ public boolean isAllowedCachedSessionReuse() { } /** - * Enables or disables sharing of session instances between multiple - * concurrent threads. + * Enables or disables sharing of session instances between multiple concurrent threads. * * @param allowedCachedSessionReuse * true if concurrent threads can access same session @@ -838,8 +846,7 @@ public void setAllowedCachedSessionReuse(boolean allowedCachedSessionReuse) { } /** - * Initializes node id. Node id is read either from property, or from - * environment variables depending on OS. + * Initializes node id. Node id is read either from property, or from environment variables depending on OS. * * @return node id */ @@ -877,15 +884,13 @@ static String initNode() { } /** - * Returns value of system property, and logs information if access to - * properties is protected. + * Returns value of system property, and logs information if access to properties is protected. * * @param key * property key * @param def * default value for property - * @return value of the property or default value if property is not defined - * or if access is protected + * @return value of the property or default value if property is not defined or if access is protected */ public static String getPropertySecured(String key, String def) { try { @@ -897,16 +902,14 @@ public static String getPropertySecured(String key, String def) { } /** - * Returns value of attribute from attribute provider if it was supplied or - * from system property if it is not present or if there is no attribute - * provider + * Returns value of attribute from attribute provider if it was supplied or from system property if it is not present + * or if there is no attribute provider * * @param key * key that identifies attribute or system property * @param defaultValue * default value for key - * @return value of the attribute, or property, or default value if it was not - * defined or if access is protected + * @return value of the attribute, or property, or default value if it was not defined or if access is protected */ public String getAttribute(String key, String defaultValue) { String value = attributes.getProperty(key); @@ -922,8 +925,7 @@ public String getAttribute(String key, String defaultValue) { } /** - * Sets attribute value. Used to add configuration items not supported by - * {@link SessionConfiguration}. + * Sets attribute value. Used to add configuration items not supported by {@link SessionConfiguration}. * * @param key * the name of the attribute @@ -950,65 +952,58 @@ public void setInterceptListeners(boolean interceptListeners) { } /** - * Returns true if distribution/replication should be used even - * when web app is marked as non-distributable. + * Returns true if distribution/replication should be used even when web app is marked as + * non-distributable. * - * @return true if distribution/replication should be used even - * when web app is marked as non-distributable. + * @return true if distribution/replication should be used even when web app is marked as + * non-distributable. */ public boolean isForceDistributable() { return forceDistributable; } /** - * Sets whether distribution/replication should be used even when web app is - * marked as non-distributable. + * Sets whether distribution/replication should be used even when web app is marked as non-distributable. * * @param forceDistributable - * true if distribution/replication should be used even - * when web app is marked as non-distributable. + * true if distribution/replication should be used even when web app is marked as + * non-distributable. */ public void setForceDistributable(boolean forceDistributable) { this.forceDistributable = forceDistributable; } /** - * Returns true if commit of attributes should be done on all - * concurrent requests to session. + * Returns true if commit of attributes should be done on all concurrent requests to session. * - * @return true if commit should be done on all concurrent - * requests + * @return true if commit should be done on all concurrent requests */ public boolean isCommitOnAllConcurrent() { return commitOnAllConcurrent; } /** - * Controls if commit of attributes should be done on all concurrent requests - * to session. + * Controls if commit of attributes should be done on all concurrent requests to session. * * @param commitOnAllConcurrent - * true if commit should be done on all concurrent - * requests + * true if commit should be done on all concurrent requests */ public void setCommitOnAllConcurrent(boolean commitOnAllConcurrent) { this.commitOnAllConcurrent = commitOnAllConcurrent; } /** - * Returns true if session should be encrypted before storing in - * repository. + * Returns true if session should be encrypted before storing in repository. * - * @return true if session should be encrypted before storing in - * repository + * @return true if session should be encrypted before storing in repository */ public boolean isUsingEncryption() { return usingEncryption; } /** - * Sets whether the session data is stored in encrypted form in repository. If - * set to true, encryption key must be set also. + * Sets whether the session data is stored in encrypted form in repository. If set to true, encryption + * key must be set also. * * @param usingEncryption * true if session data is stored in encrypted form @@ -1018,8 +1013,7 @@ public void setUsingEncryption(boolean usingEncryption) { } /** - * Returns encryption key to use. If encryption is disabled, returns - * null. + * Returns encryption key to use. If encryption is disabled, returns null. * * @return the encryption key */ @@ -1079,17 +1073,17 @@ private String loadKeyFromUrl(URL url) { public String toString() { StringBuilder builder = new StringBuilder(); builder.append("SessionConfiguration [namespace=").append(namespace).append(", node=").append(node) - .append(", sessionIdName=").append(sessionIdName).append(", maxInactiveInterval=") - .append(maxInactiveInterval).append(", distributable=").append(distributable).append(", sticky=") - .append(sticky).append(", allowedCachedSessionReuse=").append(allowedCachedSessionReuse) - .append(", interceptListeners=").append(interceptListeners).append(", forceDistributable=") - .append(forceDistributable).append(", loggingMdcActive=").append(loggingMdcActive) - .append(", usingEncryption=").append(usingEncryption).append(", loggingMdcKey=").append(loggingMdcKey) - .append(", providerConfiguration=").append(providerConfiguration).append(", repositoryFactory=") - .append(repositoryFactory).append(", sessionTracking=").append(sessionTracking).append(", encryptionKey=") - .append(encryptionKey).append(", nonCacheable=").append(nonCacheable).append(", replicationTrigger=") - .append(replicationTrigger).append(", attributes=").append(attributes).append(", commitOnAllConcurrent=") - .append(commitOnAllConcurrent).append(", timestamp=").append(timestampSufix).append("]"); + .append(", sessionIdName=").append(sessionIdName).append(", maxInactiveInterval=").append(maxInactiveInterval) + .append(", distributable=").append(distributable).append(", sticky=").append(sticky) + .append(", allowedCachedSessionReuse=").append(allowedCachedSessionReuse).append(", interceptListeners=") + .append(interceptListeners).append(", forceDistributable=").append(forceDistributable) + .append(", loggingMdcActive=").append(loggingMdcActive).append(", usingEncryption=").append(usingEncryption) + .append(", loggingMdcKey=").append(loggingMdcKey).append(", providerConfiguration=") + .append(providerConfiguration).append(", repositoryFactory=").append(repositoryFactory) + .append(", sessionTracking=").append(sessionTracking).append(", encryptionKey=").append(encryptionKey) + .append(", nonCacheable=").append(nonCacheable).append(", replicationTrigger=").append(replicationTrigger) + .append(", attributes=").append(attributes).append(", commitOnAllConcurrent=").append(commitOnAllConcurrent) + .append(", timestamp=").append(timestampSufix).append("]"); return builder.toString(); } diff --git a/session-replacement/src/main/java/com/amadeus/session/SessionManager.java b/session-replacement/src/main/java/com/amadeus/session/SessionManager.java index eb61c80..641abc0 100644 --- a/session-replacement/src/main/java/com/amadeus/session/SessionManager.java +++ b/session-replacement/src/main/java/com/amadeus/session/SessionManager.java @@ -43,6 +43,7 @@ * */ public class SessionManager implements Closeable { + private static final Logger logger = LoggerFactory.getLogger(SessionManager.class); static final String SESSIONS_METRIC_PREFIX = "com.amadeus.session"; @@ -125,6 +126,8 @@ public class SessionManager implements Closeable { public SessionManager(ExecutorFacade executors, SessionFactory factory, SessionRepository repository, SessionTracking tracking, SessionNotifier notifier, SessionConfiguration configuration, ClassLoader classLoader) { + logger.info("creation of SessionManager"); + this.repository = repository; this.tracking = tracking; this.notifier = notifier; @@ -404,6 +407,7 @@ public ScheduledFuture schedule(String timer, Runnable task, long period) { return executors.scheduleAtFixedRate(new RunnableWithTimer(timer, task), period, period, TimeUnit.SECONDS); } return executors.scheduleAtFixedRate(task, period, period, TimeUnit.SECONDS); + } /** @@ -570,6 +574,9 @@ public String encodeUrl(RequestWithSession request, String url) { */ public void reset() { + + logger.info("reset of SessionManager"); + if (reporter != null) { reporter.stop(); reporter.close(); @@ -584,6 +591,9 @@ public void reset() { */ @Override public void close() { + + logger.info("close of SessionManager"); + if (reporter != null) { reporter.close(); } diff --git a/session-replacement/src/main/java/com/amadeus/session/repository/redis/RedisConfiguration.java b/session-replacement/src/main/java/com/amadeus/session/repository/redis/RedisConfiguration.java index 4f8fe97..20b7b96 100644 --- a/session-replacement/src/main/java/com/amadeus/session/repository/redis/RedisConfiguration.java +++ b/session-replacement/src/main/java/com/amadeus/session/repository/redis/RedisConfiguration.java @@ -15,9 +15,8 @@ import com.amadeus.session.SessionConfiguration; /** - * This class encapsulates configuration of Redis servers. It provides helper - * methods to read configuratin, resolve server/sentinel/cluster member names, - * and configure JedisPool. + * This class encapsulates configuration of Redis servers. It provides helper methods to read configuratin, resolve + * server/sentinel/cluster member names, and configure JedisPool. */ public class RedisConfiguration { /** @@ -26,62 +25,65 @@ public class RedisConfiguration { public static final String METRIC_PREFIX = "com.amadeus.session"; /** - * System or configuration property that specifies that redis server(s) are - * identified using IPv4 addresses. It is recommended that only one of the - * {@link #REDIS_USE_IPV4} and {@link #REDIS_USE_IPV6} properties are set to + * System or configuration property that specifies that redis server(s) are identified using IPv4 addresses. It is + * recommended that only one of the {@link #REDIS_USE_IPV4} and {@link #REDIS_USE_IPV6} properties are set to * true. Default behavior is to use IPv4 addresses. */ public static final String REDIS_USE_IPV4 = "com.amadeus.session.redis.ipv4"; + /** - * System or configuration property that specifies that redis server(s) are - * identified using IPv6 addresses. It is recommended that only one of the - * {@link #REDIS_USE_IPV4} and {@link #REDIS_USE_IPV6} properties are set to + * System or configuration property that specifies that redis server(s) are identified using IPv6 addresses. It is + * recommended that only one of the {@link #REDIS_USE_IPV4} and {@link #REDIS_USE_IPV6} properties are set to * true. Default behavior is to use IPv4 addresses. */ public static final String REDIS_USE_IPV6 = "com.amadeus.session.redis.ipv6"; + /** - * System or configuration property that specifies expiration strategy used by - * redis. + * System or configuration property that specifies expiration strategy used by redis. */ public static final String REDIS_EXPIRATION_STRATEGY = "com.amadeus.session.redis.expiration"; + /** - * System or configuration property that specifies connection and socket - * timeout used by redis. + * System or configuration property that specifies connection and socket timeout used by redis. */ public static final String REDIS_TIMEOUT = "com.amadeus.session.redis.timeout"; + /** * Default redis timeout. */ public static final String DEFAULT_REDIS_TIMEOUT = "2000"; + /** - * System or configuration property that specifies port of redis server(s) or - * sentinel(s). + * System or configuration property that specifies port of redis server(s) or sentinel(s). */ public static final String REDIS_PORT = "com.amadeus.session.redis.port"; + /** - * System or configuration property that specifies the address(es) and - * optionally port(s) of redis servers or sentinels. + * System or configuration property that specifies the address(es) and optionally port(s) of redis servers or + * sentinels. */ public static final String REDIS_HOST = "com.amadeus.session.redis.host"; + /** - * System or configuration property that specifies the size of the pool of - * redis connections. + * System or configuration property that specifies the size of the pool of redis connections. */ public static final String REDIS_POOL_SIZE = "com.amadeus.session.redis.pool"; + /** * Default size of the redis pool. */ public static final String DEFAULT_REDIS_POOL_SIZE = "100"; + /** - * System or configuration property that specifies the redis clustering mode. - * Can be SINGLE, SENTINEL or CLUSTER. + * System or configuration property that specifies the redis clustering mode. Can be SINGLE, SENTINEL or CLUSTER. */ public static final String REDIS_CLUSTER_MODE = "com.amadeus.session.redis.mode"; + /** - * System or configuration property that specifies the name of redis master - * when using sentinel mode. + * System or configuration property that specifies the name of redis master when using sentinel mode. */ public static final String REDIS_MASTER_NAME = "com.amadeus.session.redis.master"; + /** * Default name for redis master when using sentinel mode. */ @@ -90,21 +92,35 @@ public class RedisConfiguration { static final Logger logger = LoggerFactory.getLogger(RedisConfiguration.class); static final String POOL_SIZE_PROPERTY = "pool="; + static final String CLUSTER_MODE_PROPERTY = "mode="; + static final String MASTER_NAME_PROPERTY = "master="; + static final String HOST_PROPERTY = "host="; + static final String REDIS_PORT_PROPERTY = "port="; + static final String EXPIRATION_PROPERTY = "expiration="; + static final String TIMEOUT_PROPERTY = "timeout="; String clusterMode; + String masterName; + String server; + String port; + String poolSize; + ExpirationStrategy strategy; + Boolean supportIpV6; + Boolean supportIpV4; + Integer timeout = null; public ExpirationStrategy getStrategy() { @@ -160,8 +176,7 @@ private void serverAddress(SessionConfiguration conf) { } /** - * Reads IP address support configuration. Implementation may support IPv4 and - * IPv6. + * Reads IP address support configuration. Implementation may support IPv4 and IPv6. */ private void ipSupport(SessionConfiguration conf) { if (supportIpV4 == null) { @@ -206,20 +221,19 @@ private void parseArgFromConfiguration(String arg) { } /** - * Utility method to extract host and port from configuration. Used for Redis - * cluster name resolution. + * Utility method to extract host and port from configuration. Used for Redis cluster name resolution. * * @return set containing host ip addresses and ports. */ public List hostsAndPorts() { - List hostAndPort = new ArrayList<>(); + List hostAndPorts = new ArrayList<>(); int defaultPort = Integer.parseInt(this.port); try { String[] servers = server.split("[/;]"); for (String aServer : servers) { String[] serverAndPort = aServer.split(":"); int portToUse = portToUse(serverAndPort, defaultPort); - collectHosts(hostAndPort, serverAndPort, portToUse); + collectHosts(hostAndPorts, serverAndPort, portToUse); } } catch (UnknownHostException e) { throw new IllegalArgumentException("Unable to resolve cluster host for configuration " + this, e); @@ -227,8 +241,13 @@ public List hostsAndPorts() { throw new IllegalArgumentException( "Port paramter was in server configuration. Expecting numeric values, but it was not: " + this); } - logger.debug("Resolved hosts from '{}':{} are {}", server, port, hostAndPort); - return hostAndPort; + + for (HostAndPort hostAndPort : hostAndPorts) { + logger.info("hostAndPort Host:" + hostAndPort.getHost() + "hostAndPort Port:" + hostAndPort.getPort()); + } + + logger.debug("Resolved hosts from '{}':{} are {}", server, port, hostAndPorts); + return hostAndPorts; } private void collectHosts(List hostAndPort, String[] serverAndPort, int portToUse) @@ -259,8 +278,7 @@ private int portToUse(String[] serverAndPort, int defaultPort) { } /** - * Resolves server DNS name if needed. Retrieves all IP addresses associated - * with DNS name. + * Resolves server DNS name if needed. Retrieves all IP addresses associated with DNS name. * * @param serverName * DNS name or IP address @@ -277,8 +295,7 @@ private InetAddress[] resolveServers(String serverName) throws UnknownHostExcept } /** - * Check if IP address is allowed: e.g. is address IPv6 or IPv4 and is that - * type of IP addresses allowed). + * Check if IP address is allowed: e.g. is address IPv6 or IPv4 and is that type of IP addresses allowed). * * @param host * IP address of the host @@ -317,6 +334,7 @@ public String toString() { public static class HostAndPort { final String host; + final int port; HostAndPort(String host, int port) { diff --git a/session-replacement/src/main/java/com/amadeus/session/servlet/SessionFilter.java b/session-replacement/src/main/java/com/amadeus/session/servlet/SessionFilter.java index 3aac63f..ed580eb 100644 --- a/session-replacement/src/main/java/com/amadeus/session/servlet/SessionFilter.java +++ b/session-replacement/src/main/java/com/amadeus/session/servlet/SessionFilter.java @@ -16,6 +16,7 @@ import javax.servlet.ServletRequest; import javax.servlet.ServletRequestWrapper; import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -46,7 +47,7 @@ public class SessionFilter implements Filter { */ @Override public void init(FilterConfig config) { - logger.warn("init"); + logger.info("init"); initForSession(config); } @@ -81,21 +82,45 @@ public void initForSession(FilterConfig config) { @Override public void doFilter(ServletRequest originalRequest, ServletResponse originalResponse, FilterChain chain) throws IOException, ServletException { + + SessionManager sessionManager = (SessionManager)servletContext.getAttribute(Attributes.SESSION_MANAGER); + if (sessionManager == null) { + initSessionManagement(servletContext); + } ServletRequest request = prepareRequest(originalRequest, originalResponse, servletContext); ServletResponse response = prepareResponse(request, originalResponse, servletContext); - SessionManager sessionManager = (SessionManager)servletContext.getAttribute(Attributes.SESSION_MANAGER); try { + + logger.debug("Start of SessionFilter doFilter "); // Call next filter in chain chain.doFilter(request, response); + + logger.debug("after the doFilter of SessionFilter doFilter "); + + } catch (Exception e) { + + logger.error("Error in sessionFiler catch", e); + HttpServletResponse resp = (HttpServletResponse)originalResponse; + if (resp != null) { + if (!resp.isCommitted()) { + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } + } else { + // HttpSession replacer is normally only used with HttpServletResponse so should be not null + } + + throw e; } finally { + logger.debug("inside finally of SessionFilter doFilter "); try { commitRequest(request, originalRequest, servletContext); } catch (Exception e) { - logger.error("Error into commit doFilter", e); + logger.error("Error in sessionFiler finally catch", e); ext(sessionManager, e); throw e; } + logger.debug("after finally of SessionFilter doFilter "); } } @@ -125,7 +150,7 @@ private void ext(SessionManager sessionManager, Exception e) { } } else { - logger.warn("already lokked"); + logger.warn("already locked"); } } else { logger.warn("Error into redis but the limits is not reach:" + errorTracker.size()); diff --git a/session-replacement/src/main/java/com/amadeus/session/servlet/SessionHelpers.java b/session-replacement/src/main/java/com/amadeus/session/servlet/SessionHelpers.java index 809a330..e1a481e 100644 --- a/session-replacement/src/main/java/com/amadeus/session/servlet/SessionHelpers.java +++ b/session-replacement/src/main/java/com/amadeus/session/servlet/SessionHelpers.java @@ -162,7 +162,7 @@ public MethodHandle[] initSessionManagement(ServletContext servletContext) { * */ public MethodHandle[] initSessionManagement(ServletContext servletContext, boolean reset) { - logger.warn("initSessionManagement start."); + logger.info("initSessionManagement start."); ResetManager resetManager = (ResetManager)servletContext.getAttribute(Attributes.ResetManager); if (resetManager == null) { SessionConfiguration conf = initConf(servletContext); @@ -188,26 +188,32 @@ public MethodHandle[] initSessionManagement(ServletContext servletContext, boole SessionConfiguration conf = initConf(servletContext); logger.info("{}", conf); SessionRepository repository = repository(servletContext, conf); - SessionTracking tracking = getTracking(servletContext, conf); - - ExecutorFacade executors = new ExecutorFacade(conf); - - ClassLoader classLoader = classLoader(servletContext); - SessionManager sessionManagement = new SessionManager(executors, factory, repository, tracking, notifier, conf, - classLoader); - interceptListeners = conf.isInterceptListeners(); - - if (sessionManagement.isConnected()) { - servletContext.setAttribute(Attributes.SESSION_MANAGER, sessionManagement); - logger.warn("The connection to redis is ok."); - resetManager.connected(); + if (repository.isConnected()) { + SessionTracking tracking = getTracking(servletContext, conf); + + ExecutorFacade executors = new ExecutorFacade(conf); + + ClassLoader classLoader = classLoader(servletContext); + SessionManager sessionManagement = new SessionManager(executors, factory, repository, tracking, notifier, conf, + classLoader); + interceptListeners = conf.isInterceptListeners(); + + if (sessionManagement.isConnected()) { + servletContext.setAttribute(Attributes.SESSION_MANAGER, sessionManagement); + logger.info("The connection to redis is ok."); + resetManager.connected(); + } else { + logger.warn("The connection to redis is ko."); + resetManager.notConnected(); + sessionManagement.reset(); + } } else { logger.warn("The connection to redis is ko."); resetManager.notConnected(); } } - logger.warn("initSessionManagement end."); + logger.info("initSessionManagement end."); return methods; } From d79102e0340274aff068637a4497f6212d80491e Mon Sep 17 00:00:00 2001 From: vdoleans Date: Wed, 18 Jul 2018 14:39:50 +0200 Subject: [PATCH 7/8] Fix Typo and shutdown --- .../src/main/java/com/amadeus/session/ExecutorFacade.java | 4 +--- .../main/java/com/amadeus/session/servlet/SessionFilter.java | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/session-replacement/src/main/java/com/amadeus/session/ExecutorFacade.java b/session-replacement/src/main/java/com/amadeus/session/ExecutorFacade.java index b14b4ee..f16c3e8 100644 --- a/session-replacement/src/main/java/com/amadeus/session/ExecutorFacade.java +++ b/session-replacement/src/main/java/com/amadeus/session/ExecutorFacade.java @@ -232,14 +232,12 @@ public void uncaughtException(Thread t, Throwable e) { */ public void shutdown() { logger.info("Shutting down the executor."); - executor.shutdown(); executor.shutdownNow(); - scheduledExecutor.shutdown(); scheduledExecutor.shutdownNow(); try { executor.awaitTermination(WAIT_FOR_SHUTDOWN, SECONDS); scheduledExecutor.awaitTermination(WAIT_FOR_SHUTDOWN, SECONDS); - } catch (InterruptedException e) { // NOSONAR Termination was interrupted + } catch (InterruptedException e) { // NOSONAR Termination was interrupted logger.error("Task termination thread was interrupted.", e); } } diff --git a/session-replacement/src/main/java/com/amadeus/session/servlet/SessionFilter.java b/session-replacement/src/main/java/com/amadeus/session/servlet/SessionFilter.java index b48ed2e..f5a4dc3 100644 --- a/session-replacement/src/main/java/com/amadeus/session/servlet/SessionFilter.java +++ b/session-replacement/src/main/java/com/amadeus/session/servlet/SessionFilter.java @@ -116,7 +116,7 @@ public void doFilter(ServletRequest originalRequest, ServletResponse originalRes try { commitRequest(request, originalRequest, servletContext); } catch (Exception e) { - logger.error("Error in sessionFiler finally catch", e); + logger.error("Error in sessionFilter finally catch", e); ext(sessionManager, e); throw e; } From 1f178fcbc7859e70d09de35e64a1cbfa70c258ec Mon Sep 17 00:00:00 2001 From: vdoleans Date: Thu, 26 Jul 2018 10:01:24 +0200 Subject: [PATCH 8/8] Fix Null pointer exception PTR15050935 --- .../repository/redis/RedisSessionRepository.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/session-replacement/src/main/java/com/amadeus/session/repository/redis/RedisSessionRepository.java b/session-replacement/src/main/java/com/amadeus/session/repository/redis/RedisSessionRepository.java index c6dfd07..929d4ca 100644 --- a/session-replacement/src/main/java/com/amadeus/session/repository/redis/RedisSessionRepository.java +++ b/session-replacement/src/main/java/com/amadeus/session/repository/redis/RedisSessionRepository.java @@ -18,6 +18,7 @@ import org.slf4j.LoggerFactory; import com.amadeus.session.SerializerDeserializer; +import com.amadeus.session.SessionConfiguration; import com.amadeus.session.SessionData; import com.amadeus.session.SessionManager; import com.amadeus.session.SessionRepository; @@ -114,6 +115,7 @@ public String get() { public RedisSessionRepository(RedisFacade redis, String namespace, String owner, ExpirationStrategy strategy, boolean sticky) { + this.redis = redis; this.owner = owner; this.namespace = namespace; @@ -198,7 +200,14 @@ public SessionData getSessionData(String id) { } } } - return new SessionData(id, lastAccessed, intFrom(values.get(1)), creationTime, previousOwner); + + int maxInactiveInterval = SessionConfiguration.DEFAULT_SESSION_TIMEOUT_VALUE_NUM; + byte[] maxInactiveIntervalByte = values.get(1); + if (maxInactiveIntervalByte != null && maxInactiveIntervalByte.length != 0) { + maxInactiveInterval = intFrom(maxInactiveIntervalByte); + } + + return new SessionData(id, lastAccessed, maxInactiveInterval, creationTime, previousOwner); } /**