O technologii i biznesie naszym zdaniem
Posts tagged gwt
Google Web Toolkit 2.0 oficjalnie dostępny!
grudnia 9th
Wczoraj na Google Campfire One został oficjalnie zaprezentowany Google Web Toolkit w najnowszej wersji 2.0. Nowości i zmian jest naprawdę sporo, a jedną z istotniejszych jest wprowadzenie narzędzia Speed Tracer.
Speed Tracer jest dodatkiem do przeglądarki Google Chrome, który umożliwia analizę wydajnościową aplikacji webowych (nie tylko tych tworzonych w GWT). Speed Tracer pozwala na bardzo dokładne przyjrzenie się działającej aplikacji, wliczając w to np. obserwację zdarzeń JavaScript’owych. Zamiast wymieniać następne funkcjonalności narzędzia Speed Tracer, lepiej obejrzeć krótki (1:40) tutorial, gdzie wszystko jest bardzo ładnie pokazane. Warto zwrócić uwagę na naprawdę rewelacyjny interfejs aplikacji (zrobiony oczywiście w GWT
).
Myślą przewodnią nowej wersji GWT są szybsze aplikacje webowe. Szybsze zarówno w sensie szybkości ich działania, jak i szybkości developmentu. Lista zmian i nowości jest naprawdę duża. Zwrócę więc uwagę tylko na te najważniejsze (moim zdaniem).
Wersja 2.0 zdecydowanie poprawia cykl edycja/odświeżenie przez wprowadzenie tzw. development mode, który pozwala uruchomić w trybie debug projekt GWT w dowolnej przeglądarce, a nie jednej, dedykowanej (jak to było wcześniej). Oznacza to, że nareszcie można używać Firefoksa albo Chrome’a przy tworzeniu aplikacji GWT, a wraz z nimi -- pakietu ulubionych rozszerzeń na czele z Firebugiem
. Nie obeszło się przy tej okazji bez zmiany Google Plugin for Eclipse, którym teraz można całkowicie kontrolować development mode z poziomu naszego ulubionego IDE
. Jeszcze trochę z ciekawostek: development mode działa przez sieć. Można więc “przypiąć się” do zdalnej sesji przeglądarki. Wydaje się to szczególnie przydatne dla Linuksiarzy, którzy mogą tylko zgadywać jak wygląda ich aplikacji w IE pod Windows. (Nawet z GWT pewnych rzeczy się nie przeskoczy…)
Kolejna wielka zmiana, która dla mnie osobiście wydaje się być szalenie interesująca, to wprowadzenie nowego, deklaratywnego sposobu konstruowania interfejsu użytkownika o nazwie UiBinder. Założenie jest takie, by uczynić łatwą (a przy okazji trochę wymusić) separację warstwy widoku od logiki aplikacji. Pomysł polega na tworzeniu dwóch plików dla każdego komponentu warstwy prezentacji. Aspekty widoku zawarte są w pliku .ui.xml, który stanowi “mieszankę” normalnego HTML’a oraz komponentów widoku (ang. widgets). Sama implementacja logiki aplikacji pozostaje natomiast w osobnym pliku .java. Pozwala to na bardzo wyraźną separację tych dwóch zagadnień i np. bardziej efektywną współpracę programistów oraz web designerów. Dodatkowo, w czasie kompilacji sprawdzane są wszystkie referencje między powyższymi plikami, więc nie ma mowy o żadnych literówkach i tego typu błędach. Naturalnie, Google Plugin for Eclipse wspiera to rozwiązanie w 100%, wliczając refactoring, uzupełnianie kodu itd.
Najnowszy Google Web Toolkit wprowadza również tzw. layout panels, pozwalające na dokładne rozmieszczenie elementów w obrębie strony. Nie ma co ukrywać, że używając HTML i CSS jest to duży problem, który najczęściej wymusza użycie pewnych “sztuczek”. Nawet we wcześniejszych wersjach GWT czasami trzeba było pokombinować, żeby coś wyglądało tak jak trzeba we wszystkich przeglądarkach. Nowe rozwiązanie bazuje tylko na standardzie CSS, co ma dać layout nie tylko bardziej stabilny i przewidywalny, ale również szybszy (znane są dość spore problemy wydajnościowe przy zmianie rozmiaru okna przeglądarki we wcześniejszych wersjach GWT). Layout panels, jak łatwo się domyślić, doskonale sprawdzają się w połączeniu z UiBinder.
Kluczową nową funkcjonalnością w GWT 2.0 jest programowe rozdzielanie kodu (ang. code splitting). Polega to na wskazaniu (w kodzie źródłowym), które komponenty muszą być wczytane “z góry” i są konieczne do załadowania aplikacji, a które można doczytać chwilę później. To tak trochę jak oglądanie filmu na YouTube: nie trzeba przecież wczytać całości, żeby rozpocząć oglądanie. Moim zdaniem to świetne rozwiązanie. Mamy do czynienia przecież z aplikacjami webowymi; tutaj nie może być poczucia, że coś jest “instalowane”. Taką aplikację otwieramy i już ma być; każąc użytkownikowi czekać 15 sekund na pojawienie się pierwszego ekranu, możemy go łatwo stracić. Świetne wyniki tutaj uzyskał zespół Google Wave. W chwili obecnej skompilowana, pełna funkcjonalność tej aplikacji to “ważący” prawie 1500 kB JavaScript, który trzeba przecież ściągnąć od razu. Dzięki zastosowaniu rozdzielania kodu, początkowo użytkownik ma do pobrania 200 kB (a po kompresji już tylko 80 kB), a reszta jest “dociągana” w czasie, gdy zastanawia się gdzie by tu kliknąć. Różnica właściwie o rząd wielkości! Częściowo zasługa w tym również nowej wersji kompilatora, który tak czy inaczej “odchudza” kod nawet o ponad 20%. Można bez problemu skompilować starsze aplikacje. W moim ostatnim projekcie w GWT dało to oszczędność 14% (właśnie sprawdziłem
) tak po prostu, bez dotykania kodu źródłowego.
Z mniejszych zmian, nastąpiło ulepszenie mechanizmu paczek (ang. bundles). Teraz zamykać w paczki można nie tylko grafiki, ale pliki dowolnego rodzaju. Jest również specjalny rodzaj paczki dla plików CSS, który automatycznie optymalizuje dołączone arkusze stylów.
Podsumowując, GWT 2.0 wydaje się być znaczną aktualizacją tego produktu. Poprawiono zarówno efektywność pracy z technologią (co w konsekwencji zmniejsza koszt tworzenia oprogramowania), jak i wydajność samych aplikacji. Google Web Toolkit niewątpliwie potwierdza swoją mocną pozycję na rynku nowoczesnych technologii front-end’owych dla aplikacji webowych. Dla mnie osobiście, jest to już od dawna faworyt w tej kategorii, który coraz bardziej rośnie w siłę. Gorąco zachęcam do pobrania nowej wersji biblioteki i przyjrzenia się wprowadzonym zmianom. Zainteresowanych kieruję na stronę produktu.
Google GIN, czyli dependency injection w GWT
września 4th
Wstęp
Google GIN (GWT INjection) to stosunkowo młody projekt Google, wprowadzający do Google Web Toolkit możliwość wstrzykiwania zależności (ang. dependency injection). Oparty jest na Google Guice (o którym pisałem kilka tygodni temu) i zapewnia pewien podzbiór funkcjonalności tej biblioteki. Po co więc GIN? Potrzeba wynika wprost ze specyfiki aplikacji tworzonych w GWT, która uniemożliwia zastosowanie “typowego” frameworka do wstrzykiwania zależności. Rozwinę ten temat za chwilę.
Póki co, nie ma możliwości pobrania skompilowanej biblioteki ze strony projektu (tak jak pisałem, jest to jeszcze wczesna faza rozwoju), więc pozostaje check out z publicznego repozytorium i własnoręczna kompilacja:
svn checkout http://google-gin.googlecode.com/svn/trunk/ google-gin-read-only cd google-gin-read-only ant dist
Zbudowanego JARa (./out/dist/gin.jar) oczywiście należy dołączyć do swojego projektu.
Zaczynamy!
Mamy już dostępne klasy GIN, więc można zaczynać. W regularnym Guice, po skonfigurowaniu zależności w klasie modułu i utworzeniu Injectora, obiekty pobiera się mniej więcej tak:
RegistrationService registrationService = injector.getInstance(RegistrationService.class);
W GWT jednak powyższy kod nie zadziała. Żeby być ścisłym: nie zadziała w komponentach po stronie klienta (ang. client-side). Jak wiadomo, aplikacja GWT dzieli się na stronę klienta i stronę serwera. Po stronie serwera nie ma żadnego problemu ze wstrzykiwaniem zależności. Obiekty są instancjonowane w rzeczywistym JRE (najczęściej w kontenerze serwletów) i żyją “normalnym” Javowym życiem. Można używać Guice, Spring albo dowolnego innego rozwiązania do wstrzykiwania zależności i będzie działać. Po stronie klienta wygląda to jednak zupełnie inaczej, ponieważ kod Java jest kompilowany do JavaScript, więc JRE nie istnieje (jest jedynie w niewielkim zakresie emulowane przez bibliotekę GWT). Standardowe użycie Guice nie zadziała więc z dwóch powodów:
- Na poziomie JavaScript nie istnieją klasy.
- Guice (podobnie jak większość tego typu rozwiązań) często korzysta z mechanizmu reflection Javy, który nie jest w ogóle emulowany w GWT.
GIN stosuje więc inny sposób na zapewnienie wstrzykiwania zależności. Na początek należy zaimportować moduł GIN we własnym module GWT.
<module> ... <inherits name="com.google.gwt.inject.Inject" /> ... </module>
Teraz funkcjonalność oferowana przez GIN jest dostępna w obrębie strony klienta aplikacji GWT. Dochodzimy jednak ponownie do momentu, gdy “jakoś” trzeba w końcu te zależności pobrać. W GIN używa się do tego specjalnej wersji Injectora — Ginjectora (który jednak de facto nie jest związany relacją dziedziczenia z tym pierwszym).
public interface ApplicationGinjector extends Ginjector {
ApplicationPresenter getApplicationPresenter();
}
Ginjector powinien oferować tylko komponenty potrzebne na etapie inicjalizacji aplikacji. Przy ich pobieraniu zostaną zainicjowane ich zależności, a więc również zależności tych zależności itd. W ten sposób zostanie zbudowany cały graf obiektów, a zależności automatycznie powstrzykiwane. W tym przypadku, komponentem potrzebnym na samym początku działania aplikacji jest ApplicationPresenter, który wyświetla ekran startowy. Zależności definiuje się dokładnie tak jak w Guice, czyli za pomocą adnotacji @Inject.
Jak wiadomo, Injector potrzebuje również modułu, w którym zawarte są informacje na temat komponentów.
public class ApplicationClientModule extends AbstractGinModule {
@Override
protected void configure() {
bind(ApplicationPresenter.class);
// other bindings...
}
}
Jak widać, moduł po stronie klienta w GWT dziedziczy z AbstractGinModule. Poza tym wszystko wygląda dokładnie jak w Guice. Istotnym niuansem związanym z modułami GIN jest fakt, że w przypadku nie odnalezienia powiązania dla klasy, automatycznie wywoływana jest dla niej metoda GWT.create(), przez co niektóre rzeczy (np. asynchroniczne interfejsy usług) będą działać nawet bez odpowiedniej deklaracji w klasie modułu.
Zdefiniowany moduł należy jeszcze skojarzyć z właściwym interfejsem Ginjector za pomocą adnotacji @GinModules.
@GinModules(ApplicationClientModule.class)
public interface ApplicationGinjector extends Ginjector {
ApplicationPresenter getApplicationPresenter();
}
W ten sposób, Ginjector jest w stanie skonfigurować całą aplikację na podstawie danych zawartych w określonym module. Aby to zrobić, należy go utworzyć za pomocą wywołania GWT.create() oraz pobrać początkowe obiekty.
public final class Application implements EntryPoint {
public void onModuleLoad() {
ApplicationGinjector injector = GWT.create(ApplicationGinjector.class);
ApplicationPresenter applicationPresenter = injector.getApplicationPresenter();
applicationPresenter.go(RootPanel.get());
}
}
W ten sposób, cała procedura wstrzykiwania zależności ma miejsce już w czasie kompilacji. Użycie GIN nie jest więc związane z żadnym dodatkowym narzutem przetwarzania. (Wyszłoby na to samo, gdybyśmy konfigurowali komponenty ręcznie.)
Prawie jak Guice
Z użyciem GIN jest związanych kilka niuansów, o czym wspomniałem już na samym początku. GIN to nie jest mimo wszystko to samo co Guice, tylko dla GWT. Najbardziej istotne różnice w stosunku do Guice to:
- Zamiast typów Module i AbstractModule są GinModule i AbstractGinModule.
- Zamiast typu Injector jest Ginjector z adnotacją @GinModules.
- Niemożliwe jest użycie powiązania toInstance() i prawdopodobnie nigdy nie będzie możliwe (ze względu na to, że GIN działa w czasie kompilacji, a nie wykonania).
- Na chwilę obecną nie jest możliwe definiowanie własnych zasięgów.
- Nie ma adnotacji @ImplementedBy oraz @ProvidedBy.
- Brak obsługi zależności cyklicznych.
- Brak wsparcia dla AOP.
Warto jeszcze dodać, że istnieje sposób na współpracę z regularnym Guice za pomocą klasy GinModuleAdapter, dzięki której GinModule staje się dostępny jako zwykły Module. Można więc rozważyć utworzenie wspólnej części zależności w postaci GinModule. Ponadto, zrozumienie jak działa strona klienta w GWT na pewno pomoże uniknąć wielu potencjalnych problemów z GIN.
Podsumowanie
Jak widać, w GWT również można wygodnie wstrzykiwać zależności i to korzystając z bardzo przyjaznego API znanego z Guice. Mimo, że biblioteka ta jest jeszcze nieco niedojrzała i nie doczekała się nawet wersji 1.0, moim zdaniem warto się nią zainteresować i zastosować we własnych projektach w Google Web Toolkit. Używając jej przez ostatnie kilka miesięcy nie napotkałem żadnych problemów (w szczególności ze stabilnością), a znacząco ułatwiłem sobie pracę, rezygnując z ręcznego wstrzykiwania zależności. Myślę, że Google jeszcze nie raz zaskoczy nas różnymi ciekawymi dodatkami do GWT. Póki co, zapraszam na stronę domową projektu oraz zachęcam do własnych eksperymentów z Google GIN.