Servlets 会话超时时未触发HttpSessionBindingListener.valueUnbound

Servlets 会话超时时未触发HttpSessionBindingListener.valueUnbound,servlets,jboss7.x,session-timeout,jboss-weld,Servlets,Jboss7.x,Session Timeout,Jboss Weld,我们需要在会话超时时进行一些数据库清理,所以实现了HttpSessionBindingListener,并在用户登录时向会话添加了一个对象,我们从未明确地将其从会话中删除 如果手动调用session.invalidate,则会触发HttpSessionBindingListener.valueUnbound,但问题是它不会在会话超时时触发。我在控制台中看到一个错误,但不确定问题出在哪里 登录时将对象设置为会话,注销时使会话无效: @Named("logincontroller") @Statef

我们需要在会话超时时进行一些数据库清理,所以实现了HttpSessionBindingListener,并在用户登录时向会话添加了一个对象,我们从未明确地将其从会话中删除

如果手动调用session.invalidate,则会触发HttpSessionBindingListener.valueUnbound,但问题是它不会在会话超时时触发。我在控制台中看到一个错误,但不确定问题出在哪里

登录时将对象设置为会话,注销时使会话无效:

@Named("logincontroller")
@Stateful
public class LoginController implements ILoginController, Serializable {

  @Inject
  private Credentials credentials;
  private ExternalContext ec = null;
  private HttpServletRequest request =null;
  private HttpServletResponse response=null;
  private HttpSession session=null;

  @PostConstruct
  private void getLocalVariables() {
    ec = FacesContext.getCurrentInstance().getExternalContext();
    request= (HttpServletRequest)ec.getRequest();
    session = request.getSession();
  }

  @Override
  public boolean login() {
    ... 
    credentials.setUserName(getUserName().toUpperCase());
    credentials.setUserPassword(getPassword());
    // set the object into session on user login
    session.setAttribute("credentials", credentials); 
  }

  @Override
  public void logout() {
        ...
        try {
            response.sendRedirect(path+"/faces/Exit.html");
            // invalidate the session on logout
            session.invalidate(); 
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
  }
}
实现HttpSessionBindingListener的凭据对象

@Named("credentials")
@SessionScoped
public class Credentials implements ICredentials, Serializable, HttpSessionBindingListener {
  ...
  @Override
  public void valueBound(HttpSessionBindingEvent event) {
    //do nothing
  }

  @Override
  public void valueUnbound(HttpSessionBindingEvent event) {
    try {
        // run DB scripts to clean up
        lockManager.releaseAllLocksForUser(getUserName().toUpperCase()); 
    } catch (Exception e) {
        e.printStackTrace();
    }
  }
}
堆栈跟踪错误:

15:13:03,252 INFO  [org.jboss.as.repository] (ServerService Thread Pool -- 66) WFLYDR0009: Content C:<path>jbossstudio10\runtimes\jboss-eap\standalone\data\content\62\7ccffda3936daab4d3148eb2e51584f8372592 is obsolete and will be removed
15:13:03,299 INFO  [org.jboss.as.repository] (ServerService Thread Pool -- 66) WFLYDR0002: Content removed from location C:\<path>\jbossstudio10\runtimes\jboss-eap\standalone\data\content\62\7ccffda3936daab4d3148eb2e51584f8372592\content
15:26:36,245 ERROR [stderr] (default task-22) Exception in thread "default task-22" org.jboss.weld.context.ContextNotActiveException: WELD-001303: No active contexts for scope type javax.enterprise.context.SessionScoped
15:26:36,246 ERROR [stderr] (default task-22)   at org.jboss.weld.manager.BeanManagerImpl.getContext(BeanManagerImpl.java:689)
15:26:36,246 ERROR [stderr] (default task-22)   at org.jboss.weld.bean.ContextualInstanceStrategy$DefaultContextualInstanceStrategy.getIfExists(ContextualInstanceStrategy.java:90)
15:26:36,246 ERROR [stderr] (default task-22)   at org.jboss.weld.bean.ContextualInstanceStrategy$CachingContextualInstanceStrategy.getIfExists(ContextualInstanceStrategy.java:165)
15:26:36,246 ERROR [stderr] (default task-22)   at org.jboss.weld.bean.ContextualInstance.getIfExists(ContextualInstance.java:63)
15:26:36,246 ERROR [stderr] (default task-22)   at org.jboss.weld.bean.proxy.ContextBeanInstance.getInstance(ContextBeanInstance.java:83)
15:26:36,246 ERROR [stderr] (default task-22)   at org.jboss.weld.bean.proxy.ProxyMethodHandler.getInstance(ProxyMethodHandler.java:125)
15:26:36,246 ERROR [stderr] (default task-22)   at com.facility.security.Credentials$Proxy$_$$_WeldClientProxy.valueUnbound(Unknown Source) // unknown source??
15:26:36,246 ERROR [stderr] (default task-22)   at io.undertow.servlet.core.SessionListenerBridge.attributeRemoved(SessionListenerBridge.java:132)
15:26:36,247 ERROR [stderr] (default task-22)   at io.undertow.server.session.SessionListeners.attributeRemoved(SessionListeners.java:81)
15:26:36,247 ERROR [stderr] (default task-22)   at io.undertow.server.session.InMemorySessionManager$SessionImpl.removeAttribute(InMemorySessionManager.java:500)
15:26:36,247 ERROR [stderr] (default task-22)   at io.undertow.servlet.core.SessionListenerBridge.sessionDestroyed(SessionListenerBridge.java:72)
15:26:36,247 ERROR [stderr] (default task-22)   at io.undertow.server.session.SessionListeners.sessionDestroyed(SessionListeners.java:61)
15:26:36,248 ERROR [stderr] (default task-22)   at io.undertow.server.session.InMemorySessionManager$SessionImpl.invalidate(InMemorySessionManager.java:528)
15:26:36,248 ERROR [stderr] (default task-22)   at io.undertow.server.session.InMemorySessionManager$SessionImpl$2$1.run(InMemorySessionManager.java:357)
15:26:36,248 ERROR [stderr] (default task-22)   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
15:26:36,248 ERROR [stderr] (default task-22)   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
15:26:36,248 ERROR [stderr] (default task-22)   at java.lang.Thread.run(Thread.java:748)
15:13:03252 INFO[org.jboss.as.repository](ServerService线程池--66)WFLYDR0009:Content C:jbossstudio10\runtimes\jboss eap\standalone\data\Content\62\7ccffda3936daab4d3148eb2e51584f8372592已过时,将被删除
15:13:03299信息[org.jboss.as.repository](服务器服务线程池--66)WFLYDR0002:从位置C删除的内容:\\jbossstudio10\runtimes\jboss eap\standalone\data\Content\62\7ccffda3936daab4d3148eb2e51584f8372592\Content
15:26:36245错误[stderr](默认任务-22)线程“default task-22”org.jboss.weld.context.ContextNotActiveException:weld-001303:作用域类型javax.enterprise.context.SessionScoped没有活动上下文
15:26:36246 org.jboss.weld.manager.BeanManagerImpl.getContext(BeanManagerImpl.java:689)处的错误[stderr](默认任务-22)
15:26:36246错误[stderr](默认任务-22)位于org.jboss.weld.bean.ContextualInstanceStrategy$DefaultContextualInstanceStrategy.getIfExists(ContextualInstanceStrategy.java:90)
15:26:36246 org.jboss.weld.bean.ContextualInstanceStrategy$CachingContextualInstanceStategy.getIfExists上的错误[stderr](默认任务-22)(ContextualInstanceStrategy.java:165)
15:26:36246 org.jboss.weld.bean.ContextualInstance.getIfExists(ContextualInstance.java:63)处的错误[stderr](默认任务-22)
15:26:36246 org.jboss.weld.bean.proxy.ContextBeanInstance.getInstance(ContextBeanInstance.java:83)处的错误[stderr](默认任务-22)
15:26:36246 org.jboss.weld.bean.proxy.ProxyMethodHandler.getInstance(ProxyMethodHandler.java:125)处的错误[stderr](默认任务-22)
15:26:36246 com.facility.security.Credentials$Proxy$\u$\ uWeldClientProxy.valueUnbound(未知源)//未知源处出现错误[stderr](默认任务-22)??
15:26:36246 io.undertow.servlet.core.SessionListenerBridge.attributeRemoved(SessionListenerBridge.java:132)处的错误[stderr](默认任务-22)
15:26:36247 io.undertow.server.session.SessionListeners.attributeRemoved(SessionListeners.java:81)处的错误[stderr](默认任务-22)
15:26:36247 io.undertow.server.session.InMemorySessionManager$SessionImpl.removeAttribute(InMemorySessionManager.java:500)处的错误[stderr](默认任务-22)
15:26:36247 io.undertow.servlet.core.SessionListenerBridge.sessionDestroyed(SessionListenerBridge.java:72)处的错误[stderr](默认任务-22)
15:26:36247 io.undertow.server.session.SessionListeners.sessionDestroyed(SessionListeners.java:61)处的错误[stderr](默认任务-22)
15:26:36248 io.undertow.server.session.InMemorySessionManager$SessionImpl.invalidate(InMemorySessionManager.java:528)处的错误[stderr](默认任务-22)
15:26:36248 io.undertow.server.session.InMemorySessionManager$SessionImpl$2$1.run(InMemorySessionManager.java:357)处的错误[stderr](默认任务-22)
15:26:36248 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)处的错误[stderr](默认任务-22)
15:26:36248 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)处的错误[stderr](默认任务-22)
15:26:36248 java.lang.Thread.run(Thread.java:748)处的错误[stderr](默认任务-22)
我是否需要在valueUnbound中获取新会话才能运行我的DB脚本?我认为调用valueUnbound时仍有会话。我确实搜索过,但没有结果

非常感谢您的帮助。
Env:Windows7Enterpise、JDK1.8、JBossEAP7.0.0、CDI1.2、Mojarra 2.2.12-jbossorg-2、deltaspike 1.8.1、Servlets 3.1、PrimeFaces 6.1、Oracle11g

我从未真正使用过
HttpSessionBindingListener.valueUnbound
,但CDI和servlet行为之间的事件顺序似乎有点混乱。具体地说,CDI似乎被告知在调用
HttpSessionBindingListener.valueUnbound
之前拆除会话bean。因此出现了异常-当调用该方法时,会话上下文不再处于活动状态


可能的解决方案是扭曲您的代码,不要使用
HttpSessionBindingListener.valueUnbound
,而是使用
凭据。valueUnbound
一种
@PreDestroy
方法。这样一来,每当bean被销毁时,CDI都应该调用它,不管原因是会话无效还是超时。

我从来没有真正使用过HttpSessionBindingListener.valueUnbound,但看起来CDI和servlet行为之间的事件顺序有点混乱。具体地说,CDI似乎被告知在调用
HttpSessionBindingListener.valueUnbound
之前拆除会话bean。因此出现了异常-当调用该方法时,会话上下文不再处于活动状态


可能的解决方案是扭曲您的代码,不要使用
HttpSessionBindingListener.valueUnbound
,而是使用
凭据。valueUnbound
一种
@PreDestroy
方法。这样一来,每当bean要被销毁时,CDI都应该调用它,不管原因是会话无效还是超时。

谢谢Siliarus,添加@PreDestroy方法解决了我的问题,该方法在会话超时和会话无效时都会激发OK you Siliarus,添加@PreDestroy方法解决了我的问题,该方法在会话超时和会话结束时都激发