Search code examples
vaadinvaadin7

Read and write cookies with @Push


In my vaadin application, i need to use @Push, but since i added it, i can't read and write cookies because VaadinService.getSurrentResponse()returns null because of Push. I manager cookies using this class :

import javax.servlet.http.Cookie;

import com.vaadin.server.VaadinResponse;
import com.vaadin.server.VaadinService;

public class CookieManager {
    private VaadinResponse response;

    public CookieManager(VaadinResponse response){
        this.response = response;
    }

    public Cookie getCookieByName(final String name) {
        // Fetch all cookies from the request
        Cookie[] cookies = VaadinService.getCurrentRequest().getCookies();

        // Iterate to find cookie by its name
        for (Cookie cookie : cookies) {
            if (name.equals(cookie.getName())) {
                return cookie;
            }
        }
        return null;
    }

    public Cookie createCookie(final String name, final String value, final int maxAge) {
        // Create a new cookie
        final Cookie cookie = new Cookie(name, value);

        cookie.setMaxAge(maxAge);

        // Set the cookie path.
        cookie.setPath(VaadinService.getCurrentRequest().getContextPath());

        // Save cookie
        addCookie(cookie);          

        return cookie;
    }

    private void addCookie(Cookie cookie){
        response.addCookie(cookie);
    }

    public Cookie updateCookieValue(final String name, final String value) {
        // Create a new cookie
        Cookie cookie = getCookieByName(name);

        cookie.setValue(value);

        // Save cookie
        addCookie(cookie);

        return cookie;
    }

    public void destroyCookieByName(final String name) {
        Cookie cookie = getCookieByName(name);

        if (cookie != null) {
            cookie.setValue(null);
            // By setting the cookie maxAge to 0 it will deleted immediately
            cookie.setMaxAge(0);
            cookie.setPath(VaadinService.getCurrentRequest().getContextPath());
            addCookie(cookie);
        }
    }
}

When i want to create a cookie (like at user's login), i get a nullPointerException because of the VaadinResponse being null.

So i tried to disable Push in constructor and re-enable it at the end of addCookie()method, but it disabled push for all of my application, even if i re-enable it just after the addCookiemethod.

I saw a ticket on vaadin's trac (http://dev.vaadin.com/ticket/11808) saying that will not be fixed, and someone suggested to create a regular AJAX query from server to create cookie, but i really don't know how to do.

How can i manage my cookies? i need to create AND get cookies, so javascript can't help me there, because i can't get javascript's return in vaadin, so i can't get a cookie.


Solution

  • As mentioned in the ticket, you can use JavaScript to call client code and also request a cookie value back by that. E.g.

    @Grapes([
            @Grab('org.vaadin.spring:spring-boot-vaadin:0.0.3'),
            @Grab('com.vaadin:vaadin-server:7.4.0.beta1'),
            @Grab('com.vaadin:vaadin-client-compiled:7.4.0.beta1'),
            @Grab('com.vaadin:vaadin-themes:7.4.0.beta1'),
            ])
    import com.vaadin.ui.*
    
    @org.vaadin.spring.VaadinUI
    @groovy.transform.CompileStatic
    class MyUI extends UI {
    
        protected void init(com.vaadin.server.VaadinRequest request) {
            final resultLabel = new Label()
            // provide a callback for the client to tell the cookies
            JavaScript.current.addFunction("tellCookie", { elemental.json.JsonArray arguments ->
                resultLabel.value = arguments?.get(0)?.asString()
            } as JavaScriptFunction)
            setContent(new VerticalLayout().with{
                addComponent(new Button("Set Cookie", {
                    // just simply set the cookies via JS (attn: quoting etc)
                    JavaScript.current.execute("document.cookie='mycookie=${System.currentTimeMillis()}'")
                } as Button.ClickListener))
                addComponent(new Button("Get Cookie", {
                    // tell the client to tell the server the cookies
                    JavaScript.current.execute("this.tellCookie(document.cookie)")
                } as Button.ClickListener))
                addComponent(resultLabel)
                return it
            })
        }
    }
    

    This is a running example (e.g. spring run vaadin.groovy) for testing. See the comments for the important parts.