ran-jit / tomcat-cluster-redis-session-manager

Tomcat clustering redis session manager java client.
https://github.com/ran-jit/tomcat-cluster-redis-session-manager/wiki
GNU General Public License v3.0
441 stars 208 forks source link

Error de-serializing the session object when using 2 TomEE servers #64

Open dbenesj opened 3 years ago

dbenesj commented 3 years ago

We are trying to run 3 applications on 2 TomEE (Tomcat with additional projects) servers. Both TomEE servers has configuration of your Redis session manager and pointing to the same redis. On first server session is created by calling first application. Using that cookie we are able to call the second application on the same server without issue. After that we can call the application on another TomEE server without issues. But once we try to call the application on the first server (after doing one or many requests to the second server), we get following stack trace is shown in log and receives 401 error:

29-Mar-2021 11:58:45.331 SEVERE [http-nio-8080-exec-1445] tomcat.request.session.redis.SessionManager.findSession Error occurred while de-serializing the session object..
        java.lang.IllegalStateException: On a thread without an initialized context nor a classloader mapping a deployed app
                at org.apache.openejb.cdi.ThreadSingletonServiceImpl.get(ThreadSingletonServiceImpl.java:350)
                at org.apache.openejb.cdi.ThreadSingletonServiceImpl.getContext(ThreadSingletonServiceImpl.java:326)
                at org.apache.openejb.cdi.ThreadSingletonServiceImpl.get(ThreadSingletonServiceImpl.java:361)
                at org.apache.openejb.cdi.ThreadSingletonServiceImpl.get(ThreadSingletonServiceImpl.java:69)
                at org.apache.webbeans.config.WebBeansFinder.getSingletonInstance(WebBeansFinder.java:57)
                at org.apache.webbeans.config.WebBeansContext.getInstance(WebBeansContext.java:180)
                at org.apache.webbeans.config.WebBeansContext.currentInstance(WebBeansContext.java:198)
                at org.apache.webbeans.context.PassivatingContext.readExternal(PassivatingContext.java:50)
                at java.io.ObjectInputStream.readExternalData(ObjectInputStream.java:2197)
                at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2146)
                at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1647)
                at java.io.ObjectInputStream.readObject(ObjectInputStream.java:483)
                at java.io.ObjectInputStream.readObject(ObjectInputStream.java:441)
                at org.apache.catalina.session.StandardSession.doReadObject(StandardSession.java:1587)
                at org.apache.catalina.session.StandardSession.readObjectData(StandardSession.java:1040)
                at tomcat.request.session.model.Session.readObjectData(Session.java:124)
                at tomcat.request.session.util.SerializationUtil.deserializeSessionData(SerializationUtil.java:77)
                at tomcat.request.session.redis.SessionManager.findSession(SessionManager.java:167)
                at tomcat.request.session.redis.SessionManager.findSession(SessionManager.java:31)
                at org.apache.catalina.connector.Request.isRequestedSessionIdValid(Request.java:2517)
                at org.apache.catalina.connector.RequestFacade.isRequestedSessionIdValid(RequestFacade.java:942)
                at com.cogniware.platform.api.security.UserStatusProcessor.process(UserStatusProcessor.java:56)
                at org.apache.camel.processor.DelegateSyncProcessor.process(DelegateSyncProcessor.java:63)
                at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:548)
                at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:201)
                at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:201)
                at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:97)
                at org.apache.camel.http.common.CamelServlet.doService(CamelServlet.java:213)
                at org.apache.camel.http.common.CamelServlet.service(CamelServlet.java:79)
                at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
                at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
                at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
                at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
                at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
                at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
                at org.apache.catalina.filters.RestCsrfPreventionFilter.doFilter(RestCsrfPreventionFilter.java:128)
                at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
                at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
                at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
                at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
                at org.apache.tomee.catalina.OpenEJBValve.invoke(OpenEJBValve.java:45)
                at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:666)
                at tomcat.request.session.redis.SessionHandlerValve.invoke(SessionHandlerValve.java:29)
                at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
                at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
                at org.apache.tomee.catalina.OpenEJBSecurityListener$RequestCapturer.invoke(OpenEJBSecurityListener.java:97)
                at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:690)
                at tomcat.request.session.redis.SingleSignOnValve.invoke(SingleSignOnValve.java:103)
                at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
                at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
                at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:373)
                at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
                at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
                at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1589)
                at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
                at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
                at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
                at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
                at java.lang.Thread.run(Thread.java:748)

Configuration of TomEE is exactly the same for both servers: context.xml:

    <!-- Session Sharing using Redis Cache -->
    <Valve className="tomcat.request.session.redis.SessionHandlerValve" />
    <Manager className="tomcat.request.session.redis.SessionManager" />

redis-data-cache.properties:

#-- Redis data-cache configuration

#- redis hosts ex: 127.0.0.1:6379, 127.0.0.2:6379, 127.0.0.2:6380, ....
redis.hosts=cache:6379

#- redis password
#redis.password=

#- set true to enable redis cluster mode (default value: false)
redis.cluster.enabled=false

#- set true to enable redis sentinel mode (default value: false)
redis.sentinel.enabled=false
# redis sentinel master name (default value: mymaster)
redis.sentinel.master=tomcat-redis

#- redis database (default value: 0)
#redis.database=0

#- redis connection timeout (default value: 2000 ms)
#redis.timeout=2000

#- enable redis and standard session mode. (default value: false)
# If enabled,
#   1. Must be enabled sticky session in your load balancer configuration. Else this manager may not return the updated session values.
#   2. Session values are stored in local jvm and redis.
#   3. If redis is down/not responding, requests uses jvm stored session values to process user requests. Redis comes back the values will be synced.
lb.sticky-session.enabled=false

#- session persistent policies. (default value: DEFAULT) ex: DEFAULT, SAVE_ON_CHANGE
# policies - DEFAULT, SAVE_ON_CHANGE, ALWAYS_SAVE_AFTER_REQUEST
#   1. SAVE_ON_CHANGE: every time session.setAttribute() or session.removeAttribute() is called the session will be saved.
#   2. ALWAYS_SAVE_AFTER_REQUEST: force saving after every request, regardless of whether or not the manager has detected changes to the session.
session.persistent.policies=DEFAULT,SAVE_ON_CHANGE

#- single-sign-on session timeout. (default value: 0 s (-infinite))
# 60 * 60 = 3600 = 1 hour)
redis.sso.timeout=3600

Used TomEE version: 8.0.5 Plus, which is build on Tomcat 9.0.41 User Tomcat Clustering Redis Session Manager version: 4.0 (tested also with version 3.0.5.1 with the same result) Redis versison: 6.0.4

Do you have an idea what might be wrong? For us it seems it might be a bug in the Redis session manager

dbenesj commented 3 years ago

it seems to be issue of TomEE, as when trying this with Tomcat, it works properly (actually it also properly works when first server is TomEE and second Tomcat) https://issues.apache.org/jira/browse/TOMEE-2865