Java 对于绑定到会话的对象,是否允许applicationserver在会话失效期间两次调用`valueUnbound(..)`方法?

Java 对于绑定到会话的对象,是否允许applicationserver在会话失效期间两次调用`valueUnbound(..)`方法?,java,session,jakarta-ee,websphere-liberty,Java,Session,Jakarta Ee,Websphere Liberty,我有一个web应用程序(Servlet2.4规范),它在WebSphere8.0、8.5和Tomcat8.5上运行良好。现在我们想评估应用程序是否可以在WebSphereLiberty下运行 Websphere日志文件在启动期间提供以下版本号: product = WebSphere Application Server 17.0.0.2 (wlp-1.0.17.cl170220170523-1818) 通过在浏览器中发送启动URL启动应用程序期间,某些对象将绑定到会话。例如,通过以下代码:

我有一个web应用程序(Servlet2.4规范),它在WebSphere8.0、8.5和Tomcat8.5上运行良好。现在我们想评估应用程序是否可以在WebSphereLiberty下运行

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;
    (...)
  }
  (...)
}
对象
GwgImpl
中的方法
valueUnbound()
被调用两次。由于该方法的第一次调用将变量
list
设置为
null
,因此第二次调用将导致
NullPointerException

我知道我可以通过添加if语句轻松解决此问题,但由于没有其他applicationserver存在此问题,因此我有以下问题:

对于绑定到会话的对象,是否允许applicationserver在会话失效期间调用
valueUnbound(..)
方法两次?(我还没有从servlet规范中找到明确的答案)

或者这是WebSphereApplicationServer中的一个bug

编辑 我修改了
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'

你有没有发现这一点很清楚。我观察到WAS 9的类似模式,这给我们带来了一个问题,并试图找到确定在sessionDestroyed与SessionDistributereMoved期间调用valueUnbound的最佳方法。想法?@b科尼:不幸的是没有。我最终接受了这种(对我来说)奇怪的行为,并强化了我的
valueUnbound()
方法。
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'