We are using jdeveloper 11.1.1.7
We have run into this strange issue while executing logout action. We have the following code for logout which is called from <af:commandLink> action property.
FacesContext fc = FacesContext.getCurrentInstance();
ExternalContext ec = fc.getExternalContext();
HttpServletRequest req = (HttpServletRequest) ec.getRequest();
HttpServletResponse res = (HttpServletResponse) ec.getResponse();
HttpSession ses = (HttpSession) req.getSession(false);
ses.invalidate();
res.sendRedirect(target);
fc.responseComplete();
So first time when the application loads, we checked from the weblogic console that, sessions=1 and total sessions=1. After logout, we see that sessions=1 and total sessions=2, which tells us that the existing session was invalidated but a new session was created. We created a HttpSessionListener and a HttpSessionAttributeListener to check at what point a new session is being created and found, during the session.invalidate call "oracle.adf.share.http.HttpSessionScopeAdapter" is set as an attribute to session which is possibly creating the new session. After putting a breakpoint in the attributeAdded method of HttpSessionAttributeListener, we found the stack trace as follows:
| (MySessionAttributeListener.java:12) oracle.myproject.session.MySessionAttributeListener.attributeAdded |
| (EventsManager.java:302) weblogic.servlet.internal.EventsManager.notifySessionAttributeChange |
| (SessionContext.java:793) weblogic.servlet.internal.session.SessionContext.notifySessionAttributeChange |
| (SessionData.java:589) weblogic.servlet.internal.session.SessionData.setAttribute |
| (SessionData.java:502) weblogic.servlet.internal.session.SessionData.setAttribute |
| (HttpUtil.java:117) oracle.adf.share.http.HttpUtil.setAttribute |
| (HttpSessionScopeAdapter.java:138) oracle.adf.share.http.HttpSessionScopeAdapter.getScope |
| (ServletADFContext.java:198) oracle.adf.share.http.ServletADFContext.createScope |
| (ADFContext.java:341) oracle.adf.share.ADFContext.getScope |
| (ADFContext.java:798) oracle.adf.share.ADFContext.getSessionScope |
| (BindingContext.java:619) oracle.adf.model.BindingContext.release |
| (HttpBindingContext.java:77) oracle.adf.model.servlet.HttpBindingContext.valueUnbound |
| (SessionData.java:720) weblogic.servlet.internal.session.SessionData.removeAttribute |
| (SessionData.java:702) weblogic.servlet.internal.session.SessionData.removeAttribute |
| (SessionData.java:976) weblogic.servlet.internal.session.SessionData.remove |
| (MemorySessionContext.java:69) weblogic.servlet.internal.session.MemorySessionContext.invalidateSession |
| (SessionData.java:864) weblogic.servlet.internal.session.SessionData.invalidate |
| (SessionData.java:882) weblogic.servlet.internal.session.SessionData.invalidate |
| (SessionManager.java:334) oracle.myproject.SessionManager.logout |
| |
From the stack trace it appeared that the valueUnbound method of HttpBindingContext is the triggering point of this new session being created. Note that we do not use data controls to connect to database tables in our project and we fetch data manually using jdbc. However we use contextual events and I believe that the handlers of these events are registered in data control config files. So I added the following lines, just before the session.invalidate to explicitly release the bindings:
ValueBinding vb = fc.getCurrentInstance().getApplication().createValueBinding("#{data}");
BindingContext bc = (BindingContext)vb.getValue(fc.getCurrentInstance());
bc.release();
After this we found that the session attribute "oracle.adf.share.http.HttpSessionScopeAdapter" is no longer being set, and a new session is not being created at that point. However after executing all the lines of code in the logout method, again a new session is being created. The stack trace as follows:
| (MySessionListener.java:30) oracle.MyProject.MySessionListener.sessionCreated |
| (EventsManager.java:275) weblogic.servlet.internal.EventsManager.notifySessionLifetimeEvent |
| (MemorySessionData.java:10) weblogic.servlet.internal.session.MemorySessionData.<init> |
| (MemorySessionContext.java:28) weblogic.servlet.internal.session.MemorySessionContext.getNewSession |
| (ServletRequestImpl.java:2876) weblogic.servlet.internal.ServletRequestImpl$SessionHelper.getNewSession |
| (ServletRequestImpl.java:2439) weblogic.servlet.internal.ServletRequestImpl$SessionHelper.getSessionInternal |
| (ServletRequestImpl.java:2403) weblogic.servlet.internal.ServletRequestImpl$SessionHelper.getSession |
| (ServletRequestImpl.java:1293) weblogic.servlet.internal.ServletRequestImpl.getSession |
| (HttpServletRequestWrapper.java:227) javax.servlet.http.HttpServletRequestWrapper.getSession |
| (ServletADFContext.java:197) oracle.adf.share.http.ServletADFContext.createScope |
| (ADFContext.java:341) oracle.adf.share.ADFContext.getScope |
| (ADFContext.java:798) oracle.adf.share.ADFContext.getSessionScope |
| (BindingUtils.java:79) oracle.adf.controller.binding.BindingUtils.getSessionScope |
| (BindingUtils.java:56) oracle.adf.controller.binding.BindingUtils.getBindingContext |
| (LifecycleContext.java:168) oracle.adf.controller.v2.context.LifecycleContext.getBindingContext |
| (FacesPageLifecycleContext.java:63) oracle.adf.controller.faces.context.FacesPageLifecycleContext.getBindingContainer |
| (DispatchContextualEventListener.java:36) oracle.adfinternal.controller.application.model.DispatchContextualEventListener.afterPhase |
| (ADFLifecycleImpl.java:538) oracle.adfinternal.controller.lifecycle.ADFLifecycleImpl$PagePhaseListenerWrapper.afterPhase |
| (LifecycleImpl.java:120) oracle.adfinternal.controller.lifecycle.LifecycleImpl.internalDispatchAfterEvent |
| (LifecycleImpl.java:168) oracle.adfinternal.controller.lifecycle.LifecycleImpl.dispatchAfterPagePhaseEvent |
| (ADFPhaseListener.java:310) oracle.adfinternal.controller.faces.lifecycle.ADFPhaseListener$PhaseInvokerImpl.dispatchAfterPagePhaseEvent |
| (ADFPhaseListener.java:87) oracle.adfinternal.controller.faces.lifecycle.ADFPhaseListener.afterPhase |
| (ADFLifecyclePhaseListener.java:53) oracle.adfinternal.controller.faces.lifecycle.ADFLifecyclePhaseListener.afterPhase |
| (LifecycleImpl.java:520) oracle.adfinternal.view.faces.lifecycle.LifecycleImpl._executePhase |
| (LifecycleImpl.java:207) oracle.adfinternal.view.faces.lifecycle.LifecycleImpl.execute |
| (FacesServlet.java:265) javax.faces.webapp.FacesServlet.service |
I suspected that the response.sendRedirect may be creating this new session but even after I commented this code, it does not make any difference and still a new session is being created. I have verified from Chrome console that we are not sending a duplicate request by mistake either.
Any ideas on what is actually creating this new session after session.invalidate? Any help is greatly appreciated.
Thanks