docs: @FFDCIgnore(Exception.class) //manually logged or is NoSuchElementException which we want to ignore
      private void processInvalidListeners() {
          final boolean trace = com.ibm.websphere.ras.TraceComponent.isAnyTracingEnabled();
  
          String appName = getIStore().getId();
  
          long start = System.currentTimeMillis();
  
          if (trace && tc.isDebugEnabled())
              tcInvoke(tcSessionMetaCache, "iterator");
  
          @SuppressWarnings("rawtypes")
          Iterator<Cache.Entry<String, ArrayList>> it = sessionMetaCache.iterator();
  
          if (trace && tc.isDebugEnabled())
              tcReturn(tcSessionMetaCache, "iterator", it);
  
          while (it.hasNext()) {
              if (trace && tc.isDebugEnabled())
                  tcInvoke(tcSessionMetaCache, "_iterator.next");
  
              @SuppressWarnings("rawtypes")
              Cache.Entry<String, ArrayList> entry;
              try {
                  entry = it.next();
              } catch (NoSuchElementException x) {
                  // ignore - some JCache providers might raise this instead of returning null when modified during iterator
                  entry = null;
              }
              String id = entry == null ? null : entry.getKey();
              ArrayList<?> value = id == null ? null : entry.getValue();
  
              if (trace && tc.isDebugEnabled())
                  tcReturn(tcSessionMetaCache, "_iterator.next", id, value);
  
              if (id != null && !INVAL_KEY.equals(id)) {
                  SessionInfo sessionInfo = new SessionInfo(value);
                  long lastAccess = sessionInfo.getLastAccess();
                  short listenerTypes = sessionInfo.getListenerTypes();
                  int maxInactive = sessionInfo.getMaxInactiveTime();
                  if ((listenerTypes & BackedSession.HTTP_SESSION_BINDING_LISTENER) != 0 // sessions that DO have binding listeners
                                  && maxInactive >= 0
                                  && maxInactive < (start - lastAccess) / 1000) {
  
                      if (trace && tc.isDebugEnabled())
                          Tr.debug(this, tc, "processInvalidListeners for sessionID=" + id);
  
                      CacheSession session = new CacheSession(this, id, _iStore.getStoreCallback());
                      session.initSession(_iStore);
                      session.setIsValid(true);
                      session.setIsNew(false);
                      session.updateLastAccessTime(lastAccess);
                      session.setCreationTime(sessionInfo.getCreationTime());
                      session.internalSetMaxInactive(maxInactive);
                      session.internalSetUser(sessionInfo.getUser());
                      session.setListenerFlag(listenerTypes);
  
                      long now = System.currentTimeMillis();
                      //handle the subset of session listeners
  
                      lastAccess = session.getCurrentAccessTime(); // try using lastTouch again..
  
                      try {
                          // get the session ready and read in any listeners
                          session.setIsNew(false);
                          session.getSwappableListeners(BackedSession.HTTP_SESSION_BINDING_LISTENER);
  
                          sessionInfo = sessionInfo.clone();
                          sessionInfo.setLastAccess(lastAccess);
  
                          // only invalidate those which have not been accessed since
                          // check in computeInvalidList
  
                          ArrayList<Object> list = sessionInfo.getArrayList();
  
                          if (trace && tc.isDebugEnabled())
                              tcInvoke(tcSessionMetaCache, "remove", id, list);
  
                          boolean removed = sessionMetaCache.remove(id, list);
  
                          if (trace && tc.isDebugEnabled())
                              tcReturn(tcSessionMetaCache, "remove", removed);
  
                          if (removed) {
                              // return of session done as a result of this call
                              session.internalInvalidate(true);
  
                              Set<String> propIds = sessionInfo.getSessionPropertyIds();
                              if (propIds != null && !propIds.isEmpty()) {
                                  HashSet<String> propKeys = new HashSet<String>();
                                  for (String propId : propIds)
                                      propKeys.add(createSessionAttributeKey(id, propId));
  
                                  if (trace && tc.isDebugEnabled())
                                      tcInvoke(tcSessionAttrCache, "removeAll", propKeys);
  
                                  sessionAttributeCache.removeAll(propKeys);
  
                                  if (trace && tc.isDebugEnabled())
                                      tcReturn(tcSessionAttrCache, "removeAll");
                              }
                          }
  
                          /*
                           * we don't want to update this on every invalidation with a listener that is processed.
                           * We'll only update this if we're getting close.
                           *
                           * Processing Invalidation Listeners could take a long time. We should update the
                           * NukerTimeStamp so that another server in this cluster doesn't kick off invalidation
                           * while we are still processing. We only want to update the time stamp if we are getting
                           * close to the time when it will expire. Therefore, we are going to do it after we're 1/2 way there.
                           */
                          if ((now + _smc.getInvalidationCheckInterval() * (1000 / 2)) < System.currentTimeMillis()) {
                              updateNukerTimeStamp(appName);
                              now = System.currentTimeMillis();
                          }
                      } catch (Exception e) {
                          FFDCFilter.processException(e, getClass().getName(), "652", this, new Object[] { session });
                          throw e;
                      }
                  }
              }
          }
      }