Wiemy już jak utworzyć komponent Vaadin w Vaadin oraz jak wpiąć komponent GWT do aplikacji Vaadni. Czas przyjrzeć się trochę bardziej skomplikowanemu procesowi czyli wpięciu komponentu GWT i komunikacji z nim.

Jeszcze raz komponent GWT i wpinanie go do aplikacji

Będzie w dużym skrócie. Sam kod komponentu GWT:

Listing 1. Komponent GWT

package pl.koziolekweb.vaadin.gwt.client.ui;

import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.VerticalPanel;

public class MyComponentGWT extends Composite {
	
	protected String random;

	protected Label label = new Label();

	private VerticalPanel panel = new VerticalPanel();

	public MyComponentGWT() {
		panel.add(new Label("GWT: "));
		panel.add(label);
		initWidget(panel);
	}

	protected void setRandom(String text) {
		label.setText(text);
   };
}

Następnie v-komponent, czyli rozszerzenie w komponentu GWT w Vaadin:

Listing 2. v-komponent

package pl.koziolekweb.vaadin.gwt.client.ui;

import com.vaadin.terminal.gwt.client.ApplicationConnection;
import com.vaadin.terminal.gwt.client.Paintable;
import com.vaadin.terminal.gwt.client.UIDL;

public class VMyComponentGWT extends MyComponentGWT implements Paintable {

	private ApplicationConnection client;
	private String uidlId;

	public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
		if (client.updateComponent(this, uidl, true)) {
			return;
		}
		this.client = client;
		uidlId = uidl.getId();
		setRandom(uidl.getStringVariable("random"));
	}

	@Override
	protected void setRandom(String text) {
		super.setRandom(text);
		if (uidlId == null || client == null) {
			return;
		}
		client.updateVariable(uidlId, "random", text, true);
	}

}

Tu pierwsze różnice w porównaniu ze zwykłym wpinaniem bez komunikacji. Po pierwsze metoda updateFromUIDL uzyskała „ciało”. W ciele tym pobieramy informacje o id komponentu oraz o aplikacji. Następnie aktualizujemy komponent, ale… nie wywołujemy super.setRandom() tylko samo setRandom(), które najpierw aktualizuje właściwy komponent GWT, a następnie aktualizuje stan zmiennej random. Po co to? Jak pamiętamy Vaadin jest tak naprawdę implementacją terminala webowego, dla aplikacji, której cały stan „dzieje się” po stronie serwera. Należy zatem samodzielnie serializować i deserializować dane z serwera po stronie klienta… czyli w v-komponencie.
Skoro już o serwerze mowa to jest jeszcze komponent serwerowy:

Listing 3. Komponent po stronie serwera

package pl.koziolekweb.vaadin;

import java.util.Map;

import pl.koziolekweb.vaadin.gwt.client.ui.VMyComponentGWT;

import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
import com.vaadin.ui.AbstractField;
import com.vaadin.ui.ClientWidget;

@SuppressWarnings("serial")
@ClientWidget(VMyComponentGWT.class)
public class MyComponentGWTProxy extends AbstractField {

	private String random = "";

	public MyComponentGWTProxy() {
		super();
		setValue(new String("0"));
	}

	@Override
	public void changeVariables(Object source, Map<string object=""> variables) {
		if (variables.containsKey("random") && !isReadOnly()) {
			final String newValue = (String) variables.get("random");
			setValue(newValue, true);
		}
	}

	@Override
	public void paintContent(PaintTarget target) throws PaintException {
		super.paintContent(target);
		target.addVariable(this, "random", getRandom());
	}

	public String getRandom() {
		return random;
	}

	public void setRandom(String random) {
		this.random = random;
		setValue(random);
	}

	@Override
	public Class> getType() {
		return String.class;
	}
}
</string>

W tym przypadku jest to serializacja i deserializacja danych po stronie serwera. Opiera się ona o dwie metody paintContent() i changeVariables. Pierwsza z nich pozwala na wysyłanie do klienta nowych zmiennych, druga na ich odbiór i utrwalenie po stronie serwera.

Proste 🙂