I’ll quickly post the code here. There are two files: the server-side component and the client side widget. The widget is not visible, but just reads the cookies and posts them back to server.
The server-side component has a listener that is invoked when the cookies become available at server (i.e. they have been read from the client).
ClientCookies.java (the server component):
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.itmill.toolkit.terminal.PaintException;
import com.itmill.toolkit.terminal.PaintTarget;
import com.itmill.toolkit.ui.AbstractComponent;
public class ClientCookies extends AbstractComponent {
private static final String VALUE_SEPARATOR = "\t";
private Map<String, String> cookies = new HashMap<String, String>();
private boolean reload;
private Map<String, String> setList = new HashMap<String, String>();
private Collection<UpdateListener> listeners = new ArrayList<UpdateListener>();
private boolean cookiesReadFromClient;
public ClientCookies() {
this(false);
}
public ClientCookies(boolean readAllCookies) {
this.reload = readAllCookies;
}
@Override
public String getTag() {
return "cookiemgr";
}
@Override
public void paintContent(PaintTarget target) throws PaintException {
super.paintContent(target);
if (!setList.isEmpty()) {
String[] newCookies = new String[setList.size()]
;
int i = 0;
for (String key : setList.keySet()) {
newCookies[i++]
= key + VALUE_SEPARATOR + setList.get(key);
}
target.addVariable(this, "setcookies", newCookies);
}
if (reload) {
target.addVariable(this, "getcookies", true);
target.addVariable(this, "cookies", new String[] {});
}
}
@SuppressWarnings("unchecked")
@Override
public void changeVariables(Object source, Map variables) {
super.changeVariables(source, variables);
if (variables.containsKey("cookies")) {
reload = false;
this.getCookies().clear();
Object variable = variables.get("cookies");
if (variable instanceof String[]) {
String[] newCookies = (String[]
) variable;
for (int i = 0; i < newCookies.length; i++) {
String[] cookie = newCookies[i]
.split(VALUE_SEPARATOR);
this.getCookies().put(cookie[0]
, cookie[1]
);
}
}
cookiesReadFromClient = true;
fireCookiesUpdatedEvent();
}
}
public void addListener(UpdateListener listener) {
if (listener == null)
return;
this.listeners.add(listener);
}
public void removeListener(UpdateListener listener) {
if (listener == null)
return;
this.listeners.remove(listener);
}
public void removeAllListeners() {
this.listeners.clear();
}
protected void fireCookiesUpdatedEvent() {
List<UpdateListener> copy = new ArrayList<UpdateListener>(
this.listeners);
for (UpdateListener l : copy) {
l.cookiesUpdated(this);
}
}
public interface UpdateListener {
public void cookiesUpdated(ClientCookies clientCookies);
}
public String getCookie(String name) {
if (cookies.size() <= 0) {
loadFromClient();
}
String cookie = cookies.get(name);
return "undefined".equals(cookie)? "" : cookie;
}
public Map<String, String> getCookies() {
return cookies;
}
public void setCookie(String name, String value) {
this.setList.put(name, value);
loadFromClient();
}
private void loadFromClient() {
reload = true;
requestRepaint();
}
public boolean isUpdated() {
return this.cookiesReadFromClient;
}
}
IClientCookies.java (The client-side widget):
import java.util.ArrayList;
import java.util.Collection;
import com.google.gwt.user.client.Cookies;
import com.google.gwt.user.client.ui.HTML;
import com.itmill.toolkit.terminal.gwt.client.ApplicationConnection;
import com.itmill.toolkit.terminal.gwt.client.Paintable;
import com.itmill.toolkit.terminal.gwt.client.UIDL;
public class IClientCookies extends HTML implements Paintable {
private static final String VALUE_SEPARATOR = "\t";
public IClientCookies() {
super();
setHTML("<div style=\"display:none;\"><!-- Cookies --></div>");
}
public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
if (client.updateComponent(this, uidl, true)) {
return;
}
if (uidl.hasVariable("setcookies")) {
String[] newCookies = uidl.getStringArrayVariable("setcookies");
for (int i = 0; i < newCookies.length; i++) {
String[] cookie = newCookies[i]
.split(VALUE_SEPARATOR);
Cookies.setCookie(cookie[0]
, cookie[1]
);
}
}
if (uidl.hasVariable("getcookies")) {
// Read all cookies
Collection<String> names = Cookies.getCookieNames();
Collection<String> values = new ArrayList<String>();
for (String name : names) {
values.add(name + VALUE_SEPARATOR + Cookies.getCookie(name));
}
client.updateVariable(uidl.getId(), "cookies", values.toArray(),
true);
}
}
}
in addition to these you need to modify your widgetset code to handle the component to widget mapping. Something like:
public class MyWidgetSet extends DefaultWidgetSet {
@SuppressWarnings("unchecked")
@Override
public Paintable createWidget(UIDL uidl) {
if (IClientCookies.class == classType) {
return new IClientCookies();
}
// Let the DefaultWidgetSet handle creation of default widgets
return super.createWidget(uidl);
}
@SuppressWarnings("unchecked")
@Override
/* Resolves UIDL tag name to class name. */
protected Class resolveWidgetType(UIDL uidl) {
final String tag = uidl.getTag();
if ("cookiemgr".equals(tag)) {
return IClientCookies.class;
}
// Let the DefaultWidgetSet handle resolution of default widgets
return super.resolveWidgetType(uidl);
}
}
… and compile the widgetset.