Search code examples
jsfcookiesjavabeanscdi

Saving and using a cookie with CDI


I am trying to save a Cookie upon user request, and to later use that cookie to fill in a text field. I am using Java CDI and a login bean. I am new to all three. For online resources all I can find is

@Inject @CookieParam
private String username;

and

@Inject @CookieParam("username")
private Instance<String> usernameResolver;
...
String username = usernameResolver.get();

For the first one the error message says " Unsatisfied dependencies for type [String] with qualifiers [@Default]"

For the second one the only error I get says "Failed to start context"

How should I fix this problem?

Thanks


Solution

  • As the @CookieParam package name hints, this is specific to JAX-RS, Java EE's other framefork for RESTful web services. This would only work in a JAX-RS managed resource as annotated by @Path. This won't work in a JSF or CDI managed bean as annotated by @ManagedBean or @Named.

    If you're using JSF's @ManagedBean to manage the bean, then it's available by EL-evaluating #{cookie.username} as @ManagedProperty.

    @ManagedBean
    public class Bean {
    
        @ManagedProperty("#{cookie.username}")
        private String username;
    
        // ...
    }
    

    If you're using CDI's @Named to manage the bean, then you've resort to either a custom annotation, or grabbing it as Cookie from the current FacesContext. As the former is not trivial (but actually a nice idea for OmniFaces though), I'll show only the latter:

    @Named
    public class Bean {
    
        private String username;
    
        @PostConstruct
        public void init() {
            Cookie cookie = (Cookie) FacesContext.getCurrentInstance().getExternalContext().getRequestCookieMap().get("username");
    
            if (cookie != null) {
                username = cookie.getValue();
            }
        }
    
        // ...
    }
    

    Then, in order to save it, the only way is using ExternalContext#addResponseCookie().

    FacesContext.getCurrentInstance().getExternalContext().addResponseCookie("username", username, properties);
    

    Don't forget to take into account that a cookie value is very restrictive as to allowed characters. You might want to URL-encode and -decode it upon save and retrieval. JSF utility library OmniFaces offers helper methods which do that implicitly.

    username = Faces.getRequestCookie("username");
    
    Faces.addResponseCookie("username", username, -1);
    

    Unrelated to the concrete problem, storing something sensitive like "user name" as a cookie is scary. Are you aware that cookies are manipulatable by the enduser? That the person who's visiting your webpage can easily edit a cookie value representing an "user name" to that of someone else?