/** * Seems like it called after our listeners was unbounded from http session. Looks like view scope * it destroyed. But should we call callback or not is a big question. * * @see HttpSessionBindingListener for more details */ @Override public void valueUnbound(HttpSessionBindingEvent event) { // logger.trace("Session event unbound " + event.getName()); final Set<ViewScopeViewMapListener> listeners; synchronized (sessionToListeners) { if (sessionToListeners.containsKey(event.getSession())) { listeners = sessionToListeners.get(event.getSession()); sessionToListeners.remove(event.getSession()); } else { listeners = null; } } if (listeners != null) { // I just hope that JSF context already done this job for (ViewScopeViewMapListener listener : listeners) { // As long as our callbacks can run only once - this is not such big deal listener.doCallback(); } } }
/** * Removing bean from scope and unregister it destruction callback without executing them. * * @see Scope for more details */ @Override public Object remove(String name) { Map<String, Object> viewMap = FacesContext.getCurrentInstance().getViewRoot().getViewMap(); if (viewMap.containsKey(name)) { Object removed; synchronized (viewMap) { if (viewMap.containsKey(name)) { removed = FacesContext.getCurrentInstance().getViewRoot().getViewMap().remove(name); } else { return null; } } HttpSession httpSession = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(true); Set<ViewScopeViewMapListener> sessionListeners; sessionListeners = sessionToListeners.get(httpSession); if (sessionListeners != null) { Set<ViewScopeViewMapListener> toRemove = new HashSet<>(); for (ViewScopeViewMapListener listener : sessionListeners) { if (listener.getName().equals(name)) { toRemove.add(listener); FacesContext.getCurrentInstance() .getViewRoot() .unsubscribeFromViewEvent(PreDestroyViewMapEvent.class, listener); } } synchronized (sessionListeners) { sessionListeners.removeAll(toRemove); } } return removed; } return null; }