protected void handleRedirect(FacesContext context, Throwable rootCause, ExceptionInfo info, boolean isResponseReset) throws IOException {
        ExternalContext externalContext = context.getExternalContext();
        if (externalContext.getSession(false) != null) {
            ClientWindow clientWindow = externalContext.getClientWindow();
            if (clientWindow != null && LangUtils.isNotBlank(clientWindow.getId())) {
                Map<String, ExceptionInfo> windowsMap = (Map<String, ExceptionInfo>)
                        externalContext.getSessionMap().computeIfAbsent(ExceptionInfo.ATTRIBUTE_NAME + "_map", k -> new LimitedSizeHashMap<>(5));
                windowsMap.put(clientWindow.getId(), info);
            }
            else {
                externalContext.getSessionMap().put(ExceptionInfo.ATTRIBUTE_NAME, info);
            }
        }

        Map<String, String> errorPages = PrimeApplicationContext.getCurrentInstance(context).getConfig().getErrorPages();

        String errorPage = evaluateErrorPage(errorPages, rootCause);
        String url = constructRedirectUrl(context, errorPage);

        // workaround for mojarra -> mojarra doesn't reset PartialResponseWriter#inChanges if we call externalContext#resetResponse
        if (isResponseReset && context.getPartialViewContext().isAjaxRequest()) {
            PartialResponseWriter writer = context.getPartialViewContext().getPartialResponseWriter();
            externalContext.addResponseHeader("Content-Type", "text/xml; charset=" + externalContext.getResponseCharacterEncoding());
            externalContext.addResponseHeader("Cache-Control", "no-cache");
            externalContext.setResponseContentType("text/xml");

            writer.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
            writer.startElement("partial-response", null);
            writer.startElement("redirect", null);
            writer.writeAttribute("url", url, null);
            writer.endElement("redirect");
            writer.endElement("partial-response");
        }
        else {
            // workaround for IllegalStateException from redirect of committed response
            if (externalContext.isResponseCommitted() && !context.getPartialViewContext().isAjaxRequest()) {
                PartialResponseWriter writer = context.getPartialViewContext().getPartialResponseWriter();
                writer.startElement("script", null);
                writer.write("window.location.href = '" + url + "';");
                writer.endElement("script");
                writer.getWrapped().endDocument();
            }
            else {
                externalContext.redirect(url);
            }
        }

        context.responseComplete();
    }
Builds the view if not already available. This is mostly required for ViewExpiredException's.

@param context The {@link FacesContext}.
@param throwable The occurred {@link Throwable}.
@param rootCause The root cause.
@return The unwrapped {@link Throwable}.
@throws java.io.IOException If building the view fails.
primefaces/src/main/java/org/primefaces/application/exceptionhandler/PrimeExceptionHandler.java