是否允许应用程序服务器在会话失效期间对绑定到会话的对象进行两次`valueUnbound(..)`方法调用?

时间:2017-09-04 13:34:46

标签: java session java-ee websphere-liberty

我有一个Web应用程序(Servlet 2.4规范),可以在Websphere 8.0,8.5和Tomcat 8.5上正常运行。现在我们要评估是否可以在Websphere Liberty下运行应用程序。

Websphere日志文件在启动期间提供以下版本号:

product = WebSphere Application Server 17.0.0.2 (wlp-1.0.17.cl170220170523-1818)

在应用程序启动期间,通过在浏览器中发送起始URL,某些对象将绑定到会话。例如,通过以下代码:

(...)
GwgImpl gwg = (GwgImpl)session.getAttribute(WEBKEY);
if (gwg == null) {
  gwg = new GwgImpl();
  session.setAttribute(WEBKEY, gwg);
}
(...)

GwgImpl对象由以下内容定义:

public class GwgImpl implements HttpSessionBindingListener {
  List<String> list = new ArrayList<String>();
  (...)
  public void valueBound(HttpSessionBindingEvent ev) {
  }

  public void valueUnbound(HttpSessionBindingEvent ev) {
    list.clear();
    list = null;
    (...)
  }
  (...)
}

直到现在,一切似乎都运作良好。但是当用户从应用程序注销并且我的LogoutHandler通过以下

使会话无效时
(...)
HttpSession session = request.getSession(false);
if (session != null) {
  session.invalidate();
}
(...)

对象valueUnbound()中的方法GwgImpl被调用两次。由于方法的第一次调用会将变量list设置为null,因此第二次调用会生成NullPointerException

我知道我可以通过添加if语句轻松解决此问题,但由于没有其他应用程序服务器出现此问题,我有以下问题:

是否允许应用程序服务器在会话失效期间对绑定到会话的对象进行两次调用valueUnbound(..)方法? (我还没有从servlet规范中找到明确的答案)

或者这是Websphere应用程序服务器中的错误吗?

修改

我修改了valueUnbound(..)方法,以查看两个调用的调用堆栈以及HttpSessionBindingEvent的值。

public void valueUnbound(HttpSessionBindingEvent ev) {
  logger.info("Stacktrace:");
  for (StackTraceElement stackTraceElement : Thread.currentThread().getStackTrace()) {
    logger.info("  " + stackTraceElement.toString());
  }
  logger.info("HttpSessionBindingEvent:");
  logger.info("  SessionID='" + ev.getSession().getId() + "'");
  logger.info("  Name='" + ev.getName() + "'");
  logger.info("  Value='" + ev.getValue() + "'");
  (...)
}

在我的Websphere日志文件中,我现在找到以下行:

Stacktrace:
  java.lang.Thread.getStackTrace(Unknown Source)
  com.mycorp.gwg.dao.GwgImpl.valueUnbound(GwgImpl.java:130)
  com.ibm.ws.session.http.HttpSessionObserver.sessionDestroyed(HttpSessionObserver.java:231)
  com.ibm.ws.session.SessionEventDispatcher.sessionDestroyed(SessionEventDispatcher.java:167)
  com.ibm.ws.session.StoreCallback.sessionInvalidated(StoreCallback.java:129)
  com.ibm.ws.session.store.memory.MemorySession.invalidate(MemorySession.java:236)
  com.ibm.ws.session.http.HttpSessionImpl.invalidate(HttpSessionImpl.java:317)
  com.ibm.ws.session.SessionData.invalidate(SessionData.java:256)
  com.ibm.ws.session.HttpSessionFacade.invalidate(HttpSessionFacade.java:197)
  com.mycorp.login.client.LogoutHandler.doLogout(LogoutHandler.java:154)
  (...)
HttpSessionBindingEvent:
  SessionID='X_AmenZHphA-DBkNRoOeWZu'
  Name='gwg'
  Value='null'
(...)
Stacktrace:
  java.lang.Thread.getStackTrace(Unknown Source)
  com.mycorp.gwg.dao.GwgImpl.valueUnbound(GwgImpl.java:130)
  com.ibm.ws.session.http.HttpSessionAttributeObserver.sessionAttributeRemoved(HttpSessionAttributeObserver.java:160)
  com.ibm.ws.session.SessionStateEventDispatcher.sessionAttributeRemoved(SessionStateEventDispatcher.java:142)
  com.ibm.ws.session.StoreCallback.sessionAttributeRemoved(StoreCallback.java:196)
  com.ibm.ws.session.store.memory.MemorySession.removeAttribute(MemorySession.java:537)
  com.ibm.ws.session.store.memory.MemorySession.invalidate(MemorySession.java:253)
  com.ibm.ws.session.http.HttpSessionImpl.invalidate(HttpSessionImpl.java:317)
  com.ibm.ws.session.SessionData.invalidate(SessionData.java:256)
  com.ibm.ws.session.HttpSessionFacade.invalidate(HttpSessionFacade.java:197)
  com.mycorp.login.client.LogoutHandler.doLogout(LogoutHandler.java:154)
  (...)
HttpSessionBindingEvent:
  SessionID='X_AmenZHphA-DBkNRoOeWZu'
  Name='gwg'
  Value='com.mycorp.gwg.dao.GwgImpl@b294b7c'

0 个答案:

没有答案