Search code examples
http-redirectjsfhttpsessionmojarra

JSF/Mojarra ExternalContext.redirect() creates a HttpSession


I'm playing with "stateless"/"transient" views in JSF and I noticed that invoking ExternalContext.redirect() causes a new session to be created.

So, I dug into the Mojarra (2.2.15) code:

// -> com.sun.faces.context.ExternalContextImpl:653

public void redirect(String requestURI) throws IOException {

    FacesContext ctx = FacesContext.getCurrentInstance();
    doLastPhaseActions(ctx, true);

    if (ctx.getPartialViewContext().isPartialRequest()) {
        if (getSession(true) instanceof HttpSession &&
            ctx.getResponseComplete()) {
            throw new IllegalStateException();
        }
        PartialResponseWriter pwriter;
        ResponseWriter writer = ctx.getResponseWriter();
        if (writer instanceof PartialResponseWriter) {
            pwriter = (PartialResponseWriter) writer;
        } else {
            pwriter = ctx.getPartialViewContext().getPartialResponseWriter();
        }
        setResponseContentType("text/xml");
        setResponseCharacterEncoding("UTF-8");
        addResponseHeader("Cache-Control", "no-cache");
//        pwriter.writePreamble("<?xml version='1.0' encoding='UTF-8'?>\n");
        pwriter.startDocument();
        pwriter.redirect(requestURI);
        pwriter.endDocument();
    } else {
        ((HttpServletResponse) response).sendRedirect(requestURI);
    }
    ctx.responseComplete();

}

Note that this method is the same also on JSF-2.3 GitHub master, nevertheless the check is not present at all on MyFaces

I wonder why they included getSession(true) instanceof HttpSession, it seems pointless to me.

Can anyone explain the reason why shuch a check is there?


Solution

  • This is indeed not the correct behavior. It should simply have checked if the response is an instance of HttpServletResponse. It should also have done that before invoking its sendRedirect() method which in its current form could have thrown a ClassCastException in a Portlet environment with a poorly implemented bridge.

    Technical reason for the explicit instanceof checks on javax.servlet.http.* classes is because JSF is also available for a Portlet environment. There they use javax.portlet.* API instead of javax.servlet.http.* API. A well known example which you probably ever heard about is "Liferay".