Trying to read and write cookies in Vaadin 7

Hi, i need to read and write cookies in Vaadin.

Here is my test code, but it is not working (the cookie is not being saved).

Can someone please point what am i doing wrong and if this is the standard way to deal with cookies?

PS: If i move the part where the cookie is saved to the “init()” method, the cookie is saved, but it is not valid for me, because i need to save the cookie after the button is pressed.

Regards,

Fabiano


import javax.servlet.http.Cookie;

import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinService;
import com.vaadin.server.VaadinServletRequest;
import com.vaadin.server.VaadinServletResponse;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Label;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;

/**
 * The Application's "main" class
 */
@SuppressWarnings("serial")
public class MyVaadinUI extends UI {

	@Override
	protected void init(VaadinRequest request) {
		// Read the cookie
		String test = "Cookie not found";
		Cookie[] cookies = ((VaadinServletRequest) VaadinService.getCurrentRequest()).getCookies();
		for (Cookie cookie : cookies)
			if (cookie.getName().equals("test"))
				test = cookie.getValue();

		final VerticalLayout layout = new VerticalLayout();
		layout.setMargin(true);
		setContent(layout);

		Button button = new Button(test);
		button.addClickListener(new Button.ClickListener() {
			public void buttonClick(ClickEvent event) {
				layout.addComponent(new Label("Thank you for clicking"));

				// Save the cookie
				VaadinServletResponse response = ((VaadinServletResponse) VaadinService
						.getCurrentResponse());
				response.addCookie(new Cookie("test", "Cookie found"));
			}
		});
		layout.addComponent(button);
	}

}

Well, i was unable to write a cookie outside “UI.init()” method (for example, to save the “username” and the “remember me” component values when a user clicks the “login” button).

I don´t know if i’m missing something or if it is a Vaadin limitation, but i tried many solutions proposed in the forums without success.

Anyway, i found a workaround which i will post here, because it seems there are other people having the same issue.

The solution was to create a unique identifier for each client, save this identifier in a cookie in the UI.init() method and retrieve it in the next sessions, and then i can store/retrieve any sort of information using other means (for example, java Preferences, text files, etc…) using this unique identifier.


package br.com.personalsoft.TestVaadin;

import java.util.UUID;
import java.util.prefs.Preferences;

import javax.servlet.http.Cookie;

import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinService;
import com.vaadin.server.VaadinServletRequest;
import com.vaadin.server.VaadinServletResponse;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Label;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;

/**
 * The Application's "main" class
 */
@SuppressWarnings("serial")
public class MyVaadinUI extends UI {

	private String clientId;

	@Override
	protected void init(VaadinRequest request) {
		// Read the clientId cookie
		clientId = UUID.randomUUID().toString();
		Cookie[] cookies = ((VaadinServletRequest) VaadinService.getCurrentRequest()).getCookies();
		for (Cookie cookie : cookies)
			if (cookie.getName().equals("clientId"))
				clientId = cookie.getValue();

		// Write the clientId cookie
		VaadinServletResponse response = ((VaadinServletResponse) VaadinService.getCurrentResponse());
		response.addCookie(new Cookie("clientId", clientId));

		final VerticalLayout layout = new VerticalLayout();
		layout.setMargin(true);
		setContent(layout);

		String userName = Preferences.userRoot().node(clientId).get("userName", "admin");
		boolean rememberMe = Preferences.userRoot().node(clientId).getBoolean("rememberMe", true);

		Button button = new Button("Click me");
		button.addClickListener(new Button.ClickListener() {
			public void buttonClick(ClickEvent event) {
				layout.addComponent(new Label("Thank you for clicking"));

				Preferences.userRoot().node(clientId).put("userName", "otherUser");
				Preferences.userRoot().node(clientId).putBoolean("rememberMe", false);
			}
		});
		layout.addComponent(button);
	}

}

VaadinService.getCurrentResponse().addCookie(new Cookie("test", "Cookie found"));

Works for me perfectly. Which version of Vaadin 7 are you using? I tried that with the RC-1 on a Button.ClickEvent. Therefor I don’t need to do it in the init-Method.

7.0 rc1

Regards,

Fabiano

This is not working for me either inside a Button.ClickEvent.

I don’t know how efficient this is, I also just started using Vaadin yesterday so I definitely don’t know what I am doing. Those things aside, this works inside a Button.ClickListener.


// set cookie
if (checkbox.getValue()) {
					
	Page.getCurrent().getJavaScript().execute(String.format("document.cookie = '%s=%s;';", "userdomain", domain));
	Page.getCurrent().getJavaScript().execute(String.format("document.cookie = '%s=%s;';", "username", username));
	Page.getCurrent().getJavaScript().execute(String.format("document.cookie = '%s=%s;';", "ticket", ticket));
}

I had the same problem and found the answer on the Vaadin Wiki:

add a correct path when writting the cookie:

cookie.setPath(VaadinService.getCurrentRequest().getContextPath());

i have this problem too (((

if code in to method - public void init(VaadinRequest request) {
VaadinService.getCurrentResponse().addCookie(new Cookie(“qqqq”, “qqqq”));
}
all works !!!

but if -
public void init(VaadinRequest request) {

new Button().addClickListener(new Button.ClickListener() {
@Override
public void buttonClick(Button.ClickEvent event) {
Cookie cookie= new Cookie(“www”, “www”)
cookie.setPath(VaadinService.getCurrentRequest().getContextPath());
VaadinService.getCurrentResponse().addCookie(cookie);
}
});
}
This is not working

workaround:
cookie.setPath(“/”); for root path

Vaadin version 7.4.2

None of the above is working for me, not including the clever-yet-horrible workaround above, which I have not been qutie desperate enough to try yet.

The use case is fairly simple:
In a Button’s ClickListener, set a cookie.
Then in UI.init(), try to read this cookie.

Like this:

    final Button loginButton = new Button("Login", new ClickListener() {
        @Override
        public void buttonClick(final ClickEvent event) {

// …
final Cookie cookie = new Cookie(“username”, username);
cookie.setPath(VaadinService.getCurrentRequest().getContextPath());
VaadinService.getCurrentResponse().addCookie(cookie);
}

At this point, I do indeed see a cookie in my browser, but its path is “/UIDL/”. I understand that this is due to the fact that it is set from an AJAX request.

Note that it matters not a lick what argument I give to “cookie.setPath()” above, or even if I call it at all. The path will always be “/UIDL/”.

Now… I try to read the cookie from inside my UI subclass:

public class Main extends UI {

@Override
protected void init(final VaadinRequest request) {

// …

    String username = null;
    final Cookie[] cookies = VaadinService.getCurrentRequest().getCookies();
    if (cookies != null) {
        for (final Cookie cookie : cookies) {
            if (name.equals("username")) {
                username = cookie.getValue();
            }
        }
    }

… and lo, username is null.

Please, what am I doing wrong?

Well that worked! Thanks for this hack. That’ll teach me to try following the docs…


Viritin add-on
has BrowserCookie class that should help you. It its based on similar JS haxies that you used, but at least they are hidden behind a Java API. It also allows you to read the value.

cheers,
matti

Matt, how can I set the expires time with viritin 1.61

tks

The expiration time support was added only for master and available in V8 compatible 2.0.beta2 release. Would you need a backport? I guess there is no other changes currently in queue for 7.X comptible series and would also need a different kind of code (Java 7 compatible). Maybe you could adapt the solution directly from github to your case? Or provide a pull request to V7 compatible branch with Java 7 code.

cheers,
matti