When I add a cookie as below:
FacesContext.getCurrentInstance().getExternalContext().addResponseCookie("Test", "Test", null);
Then it works well, but the cookie becomes a session cookie with max age of -1
.
When I try as below:
Map<String, Object> properties = new HashMap<>();
properties.put("domain", "test");
properties.put("maxAge", 31536000);
properties.put("secure", false);
properties.put("path","/");
FacesContext.getCurrentInstance().getExternalContext().addResponseCookie("Test", "Test", properties);
Then I don't see the cookie anywhere. I don't understand why.
I'm using Tomcat 7.
Your specific case failed because the domain was set wrongly. Cookies are domain specific. You can't set a cookie on a different domain. If you don't specify the domain, then it will default to the domain of the current request URI. The Cookie#setDomain()
is only useful if you intend to set a cookie on a common or different subdomain. E.g. if you have foo.example.com
and bar.example.com
, then you could set cookies for the other domain via that method, or set the domain to .example.com
(with the leading period!) to share the cookie between both subdomains.
So, this should do in your particular case:
String name = "cookiename";
String value = "cookievalue";
Map<String, Object> properties = new HashMap<>();
properties.put("maxAge", 31536000);
properties.put("path", "/");
externalContext.addResponseCookie(name, URLEncoder.encode(value, "UTF-8"), properties);
Note that explicitly setting the path is very important in case you intend to use the cookie webapp-wide, as it otherwise defaults to the current path which would of course fail when it's set for first time in a subfolder. Such a cookie won't be accessible in any parent folder. The other answer here above doesn't properly take this into account as it unnecessarily and incorrectly reuses an existing cookie instead of creating it brand new. See also a.o. In Java servlet, cookie.getMaxAge() always returns -1.
As to retrieving a cookie in JSF, use ExternalContext#getRequestCookieMap()
:
Cookie cookie = (Cookie) externalContext.getRequestCookieMap().get(name);
String value = URLDecoder.decode(cookie.getValue(), "UTF-8");
// ...
Note that I'm URL-encoding/decoding the cookie value before setting/retrieving, as you would otherwise run into trouble like asked in the following related questions: Why do cookie values with whitespace arrive at the client side with quotes? and java.lang.IllegalArgumentException: Control character in cookie value or attribute.
That said, I do agree that the JSF API is somewhat opaque as to retrieving and setting cookies. The JSF utility library OmniFaces has several useful utility methods in the Faces
utility class for the purpose, which implicitly sets sane defaults as cookie properties and URL-encodes/decodes the value.
// Getting a cookie value.
String value = Faces.getRequestCookie(name);
// Setting a session cookie in current path.
Faces.addResponseCookie(name, value, -1);
// Setting a session cookie in current domain.
Faces.addResponseCookie(name, value, "/", -1);
// Setting a (sub)domain-wide session cookie.
Faces.addResponseCookie(name, value, ".example.com", "/", -1);
// Setting a cookie with max age of 1 year in current domain.
Faces.addResponseCookie(name, value, "/", (int) TimeUnit.DAYS.toSeconds(365));
// Removing a cookie from current domain.
Faces.removeResponseCookie(name, "/");
Try this:
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(request.getContextPath());
}
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;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With