4

I've this code to set a cookie during page load, however it is not working:

MarkUp:

<ui:fragment rendered="#{surveyWebBean.showQuestions}">
    <ui:include src="/general/survey.xhtml" />
</ui:fragment>

Code:

SurveyWebBean.java

@ManagedBean(name = "surveyWebBean")
@SessionScoped
public class EncuestasWebBean extends BaseBean {

    private boolean showQuestions;

    @PostConstruct
    public void init() {
        showQuestions = true;
        UUID uuid = UUID.randomUUID();
        CookieHelper ch = new CookieHelper();
        ch.setCookie("COOKIE_UUID_SURVEY", uuid.toString(), 60 * 60 * 24 * 365 * 10);
    }

    //Getters and Setters
}

CookieHelper.java

public class CookieHelper {

    public void setCookie(String name, String value, int expiry) {

        FacesContext facesContext = FacesContext.getCurrentInstance();
        HttpServletRequest request = (HttpServletRequest) facesContext.getExternalContext().getRequest();
        Cookie cookie = null;
        Cookie[] userCookies = request.getCookies();

        if (userCookies != null && userCookies.length > 0) {
            for (int i = 0; i < userCookies.length; i++) {
                if (userCookies[i].getName().equals(name)) {
                    cookie = userCookies[i];
                    break;
                }
            }
        }

        if (cookie != null) {
            cookie.setValue(value);
        } else {
            cookie = new Cookie(name, value);
            cookie.setPath("/");
        }

        cookie.setMaxAge(expiry);
        HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();
        response.addCookie(cookie);
    }

    public Cookie getCookie(String name) {

        FacesContext facesContext = FacesContext.getCurrentInstance();
        HttpServletRequest request = (HttpServletRequest) facesContext.getExternalContext().getRequest();
        Cookie cookie = null;
        Cookie[] userCookies = request.getCookies();

        if (userCookies != null && userCookies.length > 0) {
            for (int i = 0; i < userCookies.length; i++) {
                if (userCookies[i].getName().equals(name)) {
                    cookie = userCookies[i];
                    return cookie;
                }
            }
        }
        return null;
    }
}

However, when I try to retrieve the cookie, or check it in the Google Chrome inspector or local data viewer, it doesn't exits

Any Idea?

Tiny
  • 27,221
  • 105
  • 339
  • 599
Colanta
  • 87
  • 1
  • 6
  • Although the place to set a cookie is fully dependent upon the functional requirements (must be set/added before the response has been committed/sent), why are you setting a cookie in a method decorated by `@PostConstruct` inside a session scoped JSF managed bean? That method `init()` will be invoked only once per HTTP session hereby not during every request and if you wanted to verify whether a cookie is really sent by the server or not, you could do it by writing some JavaScript code (since it is not an HttpOnly cooke). – Tiny Jan 13 '15 at 20:07

1 Answers1

5

It appears that the bean is for the first time referenced when the response is rendered. You can't set cookies during render response phase. Cookies are set in HTTP response headers. But at the moment JSF is busy generating some HTML output to the response body, the response headers are likely already sent for long.

You need to set the cookie before the first bit is being written to the response body.

You can use <f:event type="preRenderView"> to invoke a bean listener method right before the render response actually starts.

<f:event type="preRenderView" listener="#{surveyWebBean.init}" />
public void init() { // (remove @PostConstruct!)
    if (showQuestions) {
        return; // Already initialized during a previous request in same session.
    }

    showQuestions = true;
    UUID uuid = UUID.randomUUID();
    CookieHelper ch = new CookieHelper();
    ch.setCookie("COOKIE_UUID_SURVEY", uuid.toString(), 60 * 60 * 24 * 365 * 10);
}

Unrelated to the concrete problem, as to CookieHelper, perhaps you found them in a JSF 1.x based resource, but you need to know that since JSF 2.0 there are new cookie related methods on ExternalContext such as getRequestCookieMap() which should simplify obtaining the cookie. The Faces utility class of JSF utility librarty OmniFaces has also some cookie related methods.

Faces.addResponseCookie("cookieName", cookieValue, "/", 60 * 60 * 24 * 365 * 10);
String cookieValue = Faces.getRequestCookie("cookieName");
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555