会话超时时不会触发HttpSessionBindingListener.valueUnbound

时间:2018-02-23 16:46:23

标签: servlets jboss7.x session-timeout jboss-weld

我们需要在会话超时时进行一些数据库清理,因此实现了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();
    }
  }
}

错误Stacktrace:

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)

我是否需要在valueUnbound中获取新会话才能运行我的数据库脚本?我认为在调用valueUnbound时我们仍然有会话。我没有搜索stackoverflow,但无济于事。

非常感谢任何帮助。 环境:Windows 7 Enterrpise,JDK 1.8,JBoss EAP 7.0.0,CDI 1.2,Mojarra 2.2.12-jbossorg-2,deltaspike 1.8.1,Servlets 3.1,PrimeFaces 6.1,Oracle 11g

1 个答案:

答案 0 :(得分:2)

我从未真正使用HttpSessionBindingListener.valueUnbound,但看起来事件的顺序在CDI和servlet行为之间有点混乱。具体来说,看起来CDI被告知在调用HttpSessionBindingListener.valueUnbound之前拆除会话bean。因此异常 - 当应该调用该方法时,您不再激活会话上下文。

可能的解决方案是扭曲代码并不使用 HttpSessionBindingListener.valueUnbound,而是使Credentials.valueUnbound成为@PreDestroy方法。这样,无论原因是会话失效还是超时,只要该bean被销毁,它就应该被CDI调用。