我们需要在会话超时时进行一些数据库清理,因此实现了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
答案 0 :(得分:2)
我从未真正使用HttpSessionBindingListener.valueUnbound
,但看起来事件的顺序在CDI和servlet行为之间有点混乱。具体来说,看起来CDI被告知在调用HttpSessionBindingListener.valueUnbound
之前拆除会话bean。因此异常 - 当应该调用该方法时,您不再激活会话上下文。
可能的解决方案是扭曲代码并不使用 HttpSessionBindingListener.valueUnbound
,而是使Credentials.valueUnbound
成为@PreDestroy
方法。这样,无论原因是会话失效还是超时,只要该bean被销毁,它就应该被CDI调用。