Miś push-upek z Finlandii

Dawno temu opisałem jak zintegrować ICE Push z Vaadin z pomocą Guice. Tamto dotyczyło Vaadin 6.x. Dziś to samo tyle, że z Vaadin 7.1.

Wstęp

Gdy pojawiły się pierwsze informacje o nowej „dużej” wersji Vaadin praktycznie od razu zaczęto zastanawiać się nad integracją Vaadin z Server Push. Początkowo miało to nastąpić już w wersji 7.0 jednak z różnych przyczyn przesunięto tą opcję do wersji 7.1. Wersja ta ukazała się parę dni temu zatem czas najwyższy przyjrzeć się nowemu rozwiązaniu.

Podstawy

Po wygenerowaniu projektu za pomocą mavena otrzymamy klasę MyVaadinUI z konfiguracją w stylu Servlets 3.0. Będzie ona zawierać klasę statyczną Servlet:

Listing 1. Klasa Servlet

@WebServlet(value = "/*", asyncSupported = true)
	@VaadinServletConfiguration(productionMode = false, 
		ui = MyVaadinUI.class, 
		widgetset = "pl.koziolekweb.vaadin.push.AppWidgetSet")
	public static class Servlet extends VaadinServlet {
	}

Najważniejszym parametrem dla nas jest asyncSupported, ktory musi mieć wartość true. Jeżeli korzystasz ze starszej wersji serwletów i pliku web.xml musisz dodać ten parametr do konfiguracji serwletu Vaadin.

Kolejnym krokiem jest zaadnotowanie naszej klasy za pomocą @Push. W ten sposób oznaczamy klasę jako wykorzystującą technologię Comet/Server Push. Styknie. Nasza aplikacja jest gotowa do działania.

Zegar

Za klasę zegara posłuży nam prosta klasa rozszerzająca TimerTask:

Listing 2. Klasa ClockTask

class ClockTask extends TimerTask {

	private final MyVaadinUI ui;

	public ClockTask(MyVaadinUI ui) {
		this.ui = ui;
	}

	@Override
	public void run() {
		String message = new Date().toString();
		ui.update(message);
		System.out.println(message);

	}
}

Trochę to bezczelnie zrobione, bo walę bezpośrednio do głównej klasy UI, ale… generalnie polecam dobudować sobie interfejs zgodny z przekonaniami. Tak samo ze sposobem wysyłania komunikatów (o tym następny wpis). Tu prosty przykład.

Uruchomienie

Czas najwyższy poskładać wszystko do kupy. Poniżej metoda init aplikacji. Chyba wszystko jasne 🙂

Listing 3. Metoda init

@Override
	protected void init(VaadinRequest request) {
		final VerticalLayout layout = new VerticalLayout();
		layout.setMargin(true);
		setContent(layout);
		timeLabel = new Label();

		Button start = new Button("Start");
		start.addClickListener(new Button.ClickListener() {
			public void buttonClick(ClickEvent event) {

				TimerTask task = new ClockTask(me());
				timer.schedule(task, 1000, 1000);
			}
		});

		Button stop = new Button("Stop");
		stop.addClickListener(new Button.ClickListener() {
			public void buttonClick(ClickEvent event) {
				timer.cancel();
				timer = new Timer();
			}
		});
		layout.addComponent(start);
		layout.addComponent(stop);
		layout.addComponent(timeLabel);
	}

	public MyVaadinUI me(){
		return this;
	}

Podsumowanie

Jak widać całość jest bardzo prosta. Jest tu jednak kilka drobnych pułapek. Pierwszą z nich jest metoda accept, przyjmująca Runnable, ale nie odpalająca oddzielnego wątku. Niby szczegół, ale znając życie wiele osób automatycznie kojarzy ten interfejs z wątkami. Po drugie jeżeli już korzystamy z wątków to trzeba to robić bardzo ostrożnie ponieważ wątki wewnątrz serwletów zawsze lubiły strzelać fochy.

W sumie jest to fajne rozwiązanie.

Na koniec ciekawostka jak podaje JRebel za pomocą swojego trackera zaoszczędzonego czasu w trakcie pracy nad tym tekstem dzięki użyciu JRebela zaoszczędziłem 51 minut. Jak klikniecie w powyższy link to możecie śledzić moje „oszczędności”.

2 myśli na temat “Miś push-upek z Finlandii

  1. Drogi Koziołku, skoro już bawiłeś się pushem, a wcześniej Vaadinem + shiro, to czy mógłbyś wziąć pod lupę sprawę połączenia autoryzacji i wykorzystania mechanizmu Push? Przez ten mechanizm, który de facto wykorzystuje Websockets, dzieją się jaja na tle identyfikacji użytkownika we wspomnianym Shiro, a szkoda odrzucać któryś z nich.

  2. W Vaadin jest to trochę inaczej, bo można upchnąć usera bezpośrednio do aplikacji i korzystać z danych z poziomu „ponad sesją”.

Napisz odpowiedź

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax