title: How should a scoped bean trigger session creation in Hazelcast
body: <p>I am using spring-web (4.1.7) with spring-security-oauth2 (2.0.12) and hazelcast (3.3).</p>
  
  <p>While testing this a user (with no session) visits the site and clicks on the link to start OpenId Connect login.</p>
  
  <p>I have added a HttpSessionListener to check when the session is created.</p>
  
  <p>The OAuth2RestTemplate is used to perform authentication and contains this line:
  OAuth2AccessToken accessToken = context.getAccessToken();</p>
  
  <p>The context object is a OAuth2ClientContext bean with session scope and it seems that using this object (not instantiating it) triggers creation of a session (and the context is stored in the session).</p>
  
  <p>So far so good, however the problem I have is that I am using Hazelcast for session replication and no Hazelcast session gets created.  This is a problem because when the request finishes and no Hazelcast session is found for the HttpSession then the Hazelcast filter will destroy the HttpSession.</p>
  
  <p>My question is, how should creation of a Hazelcast filter be triggered ?
  The stacktrace for creating the session shows that we do not make any call to Hazelcast to create the session:</p>
  
  <pre><code>WebSessionListener.sessionCreated(HttpSessionEvent) line: 15    
  StandardSession.tellNew() line: 367 
  StandardSession.setId(String) line: 341 
  StandardManager(ManagerBase).createSession(String) line: 857    
  StandardManager.createSession(String) line: 291 
  Request.doGetSession(boolean) line: 2606    
  Request.getSession(boolean) line: 2316  
  RequestFacade.getSession(boolean) line: 841 
  ServletRequestAttributes.getSession(boolean) line: 111  
  ServletRequestAttributes.getSessionMutex() line: 244    
  SessionScope.get(String, ObjectFactory&lt;?&gt;) line: 91 
  DefaultListableBeanFactory(AbstractBeanFactory).doGetBean(String, Class&lt;T&gt;, Object[], boolean) line: 337    
  DefaultListableBeanFactory(AbstractBeanFactory).getBean(String) line: 194   
  SimpleBeanTargetSource.getTarget() line: 35 
  JdkDynamicAopProxy.invoke(Object, Method, Object[]) line: 187   
  $Proxy322.getAccessToken() line: not available  
  OAuth2RestTemplate.getAccessToken() line: 169   
  </code></pre>
  
  <p>I have some some hacking and found that if I put in a call to
  request.getSession(true);
  This will create the both</p>
  
  <ol>
  <li>the HttpSession</li>
  <li>The Hazelcast Session</li>
  </ol>
  
  <p>The stack trace shows we go through the Hazelcast method SpringAwareWebFilter.createNewSession before creating the HttpSession.</p>
  
  <p>So the issue I have seems to be:</p>
  
  <p>When using a RequestWrapper(HttpServletRequestWrapper).getSession()
  to get/create a session this is Hazelcast aware.  </p>
  
  <p>However when spring tries to create a session (triggered when a session scoped bean is used), it is not Hazelcast aware.</p>
  
  <p>Is this expected behaviour i.e. spring does not know to create the Hazelcast session and I have to find some workaround ?  Or can anyone recommend any further way to debug this ?</p>
  
  <p>In web.xml the hazelcast config is:</p>
  
  <pre><code>    &lt;filter&gt;
          &lt;filter-name&gt;hazelcast-filter&lt;/filter-name&gt;
          &lt;filter-class&gt;com.hazelcast.web.spring.SpringAwareWebFilter&lt;/filter-class&gt;
          &lt;init-param&gt;
              &lt;param-name&gt;map-name&lt;/param-name&gt;
              &lt;param-value&gt;sessions&lt;/param-value&gt;
          &lt;/init-param&gt;
  
          &lt;init-param&gt;
              &lt;param-name&gt;sticky-session&lt;/param-name&gt;
              &lt;param-value&gt;false&lt;/param-value&gt;
          &lt;/init-param&gt;
  
          &lt;init-param&gt;
              &lt;param-name&gt;cookie-name&lt;/param-name&gt;
              &lt;param-value&gt;hazelcast.session&lt;/param-value&gt;
          &lt;/init-param&gt;
  
          &lt;init-param&gt;
              &lt;param-name&gt;cookie-secure&lt;/param-name&gt;
              &lt;param-value&gt;false&lt;/param-value&gt;
          &lt;/init-param&gt;
  
          &lt;init-param&gt;
              &lt;param-name&gt;cookie-http-only&lt;/param-name&gt;
              &lt;param-value&gt;false&lt;/param-value&gt;
          &lt;/init-param&gt;
  
          &lt;init-param&gt;
              &lt;param-name&gt;debug&lt;/param-name&gt;
              &lt;param-value&gt;true&lt;/param-value&gt;
          &lt;/init-param&gt;
  
          &lt;init-param&gt;
              &lt;param-name&gt;config-location&lt;/param-name&gt;
              &lt;param-value&gt;hazelcast-geneva.xml&lt;/param-value&gt;
          &lt;/init-param&gt;
  
  
          &lt;init-param&gt;
              &lt;param-name&gt;shutdown-on-destroy&lt;/param-name&gt;
              &lt;param-value&gt;true&lt;/param-value&gt;
          &lt;/init-param&gt;
      &lt;/filter&gt;
      &lt;filter-mapping&gt;
          &lt;filter-name&gt;hazelcast-filter&lt;/filter-name&gt;
          &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
          &lt;dispatcher&gt;FORWARD&lt;/dispatcher&gt;
          &lt;dispatcher&gt;INCLUDE&lt;/dispatcher&gt;
          &lt;dispatcher&gt;REQUEST&lt;/dispatcher&gt;
      &lt;/filter-mapping&gt;
  </code></pre>
  
  <p>For reference, if I force a call to request.getSession and this call goes through the Hazelcast filters WebFilter and SpringAwareWebFilter the stack chain is like this (compare to the stack above where the Hazelcast filters are missing)</p>
  
  <pre><code>WebSessionListener.sessionCreated(HttpSessionEvent) line: 15    
  StandardSession.tellNew() line: 367 
  StandardSession.setId(String) line: 341 
  StandardManager(ManagerBase).createSession(String) line: 857    
  StandardManager.createSession(String) line: 291 
  Request.doGetSession(boolean) line: 2606    
  Request.getSession(boolean) line: 2316  
  RequestFacade.getSession(boolean) line: 841 
  WebFilter$RequestWrapper(HttpServletRequestWrapper).getSession(boolean) line: 255   
  WebFilter$RequestWrapper.getOriginalSession(boolean) line: 533  
  SpringAwareWebFilter(WebFilter).createNewSession(WebFilter$RequestWrapper, String) line: 307    
  SpringAwareWebFilter.createNewSession(WebFilter$RequestWrapper, String) line: 47    
  WebFilter$RequestWrapper.getSession(boolean) line: 605  
  WebFilter$RequestWrapper.getSession(boolean) line: 515  
  RequestWrapper(HttpServletRequestWrapper).getSession(boolean) line: 255 
  </code></pre>
  
  <h1>Update</h1>
  
  <p>I found that when a method is called on my session scoped bean that it triggers a call to ServletRequestAttributes.getSession(boolean).</p>
  
  <p>This object has an attribute called request on which it calls getSession(boolean).
  If this request object was the WebFilter$RequestWrapper created by the Hazelcast filter, this I suspect everything would work fine.</p>
  
  <p>However ServletRequestAttributes is initialised with a HttpServletRequest (not wrapped by Hazelcast) well before the Hazelcast filter doFilter is called.</p>
  
  <p>It does not seem possible to update the request attribute in ServletRequestAttributes, but maybe there is some way to create a new one.</p>
  
  <h1>Update 2</h1>
  
  <p>I was using RequestContextListener, it gets triggered before any of the filters and sets the request object in ServletRequestAttributes before the Hazelcast filter has a chance to wrap it.  I removed RequestContextListener and replaced it with RequestContextFilter (as seems to be what they did in spring boot: <a href="https://github.com/spring-projects/spring-boot/issues/2637" rel="nofollow noreferrer">https://github.com/spring-projects/spring-boot/issues/2637</a>).  This makes sure when ServletRequestAttributes is initialized, it gets the Hazelcast request object.</p>