diff --git a/jsf-ri/src/main/java/com/sun/faces/application/view/ViewScopeContextManager.java b/jsf-ri/src/main/java/com/sun/faces/application/view/ViewScopeContextManager.java index f56ce678ce..ea730985d2 100644 --- a/jsf-ri/src/main/java/com/sun/faces/application/view/ViewScopeContextManager.java +++ b/jsf-ri/src/main/java/com/sun/faces/application/view/ViewScopeContextManager.java @@ -37,6 +37,7 @@ * only if the new code is made subject to such option by the copyright * holder. */ +// Portions Copyright [2018] [Payara Foundation and/or its affiliates] package com.sun.faces.application.view; import com.sun.faces.util.FacesLogger; @@ -172,7 +173,18 @@ private void destroyBeans( CreationalContext creationalContext = beanManager.createCreationalContext(contextual); // We can no longer get this from the contextObject. Instead we must call // beanManager.createCreationalContext(contextual) - contextual.destroy(viewMap.get(contextObject.getName()), creationalContext); + Object contextualInstance = viewMap.get(contextObject.getName()); + + // Contextual instance may be null if already removed from view map (and thus already destroyed). + // This can happen when a mid-request navigation happens and a new view root is being set, and then + // in the same request a session.invalidate is called. + // See https://github.com/javaserverfaces/mojarra/issues/3454 + // Also see https://github.com/payara/Payara/issues/2506 for why we can't just clean the contextMap + // (it contains abstract descriptors for all instances, not just the one we want to destroy here). + if (contextualInstance != null) { + contextual.destroy(contextualInstance, creationalContext); + } + removalNameList.add(contextObject.getName()); } @@ -182,7 +194,6 @@ private void destroyBeans( viewMap.remove(name); } - contextMap.clear(); } }