W tym artykule przedstawię w sposób ogólny technologię Vaadin – framework w języku Java, a następnie omówię kilka różnic występujących między wersją 7 a 8 tego frameworka. Dodatkowo wyjaśnię w jaki sposób można przeprowadzić migrację między tymi wersjami zgodnie z zaleceniami twórców Vaadina. Zapraszam do przeczytania.
Wstęp – technologia Vaadin
Vaadin jest frameworkiem umożliwiającym tworzenie aplikacji webowych w języku Java. Jego podstawową zaletą jest to, że nie wymaga on dużej znajomości technologii frontendowych (co najwyżej podstawy) od programisty. Jeśli jednak programista potrzebuje użyć tych technologii w pisanej aplikacji w niestandardowy sposób, Vaadin daje taką możliwość i pozwala używać styli CSS, JavaScript, HTML5 itp. Sposób tworzenia interfejsu użytkownika w frameworku Vaadin przypomina tworzenie aplikacji desktopowej w Swingu. Programista tworzy UI z komponentów dostarczonych przez Vaadina (np. TextField, ComboBox) i następnie może zarządzać ich ułożeniem stosując odpowiednie layouty. Aplikację w stylu „Hello World” możemy utworzyć w bardzo prosty sposób np. pobierając plugin do Eclipse (Vaddin plugin for Eclipse), a następnie utworzyć projekt za pomocą archetypu mavena (file -> new -> other -> Vaadin Project). Utworzona w ten sposób aplikacja w Vaadinie 7 składa się z elementów przedstawionych na rysunku 1.1
Jak widać na rysunku 1.1 struktura nie jest bardzo złożona, istnieje tylko jedna klasa oraz kilka plików .css, .scss i .ico odpowiadających za style wyglądu aplikacji. Istotną rzeczą jest jednak klasa MyUI, której zawartość prezentuje Listing 1.2:
@Theme("mytheme")
public class MyUI extends UI {
private static final long serialVersionUID = 2123628334309501295L;
@Override
protected void init(VaadinRequest vaadinRequest) {
final VerticalLayout layout = new VerticalLayout(); // stworzenie layoutu pionowego
// (komponenty będą ułożone jeden pod drugim)
final TextField name = new TextField(); // stworzenie pola textowego
name.setCaption("Type your name here:"); // dodanie podpisu do pola textowego
Button button = new Button("Click Me"); // Stworzenie przycisku
layout.addComponents(name, button); // dodanie pola textowego i przycisku do layoutu
layout.setMargin(true); // margines dla layoutu
layout.setSpacing(true); // margines między komponentami w layoucie
setContent(layout); // ustawienie layoutu jako zawartości widoku strony
}
@WebServlet(urlPatterns = "/*", name = "MyUIServlet", asyncSupported = true)
@VaadinServletConfiguration(ui = MyUI.class, productionMode = false)
public static class MyUIServlet extends VaadinServlet {
}
}
Listing 1.2 Klasa MyUI
Klasa MyUI rozszerza klasę UI odpowiadającą treści wyświetlanej w przeglądarce. W metodzie init można tworzyć konkretny widok z komponentów – tak też zrobiono na Listingu 1.2. Warto zwrócić uwagę także na wewnętrzna klasę statyczną MyUIServlet, dzięki której została dokonana niezbędna konfiguracja:
- @WebServlet wskazuje na jakie żądanie ma być zmapowany servlet, jego nazwę, oraz czy servlet ma wspierać operacje asynchroniczne.
- @VaadinServletConfiguration wskazuje na jaki widok ma być przekierowany użytkownik oraz w jakim trybie ma pracować (produkcyjnym lub nie).
Efekt działania utworzonej aplikacji został przedstawiony na rysunku 1.3.
Jak na aplikację składającą się z jednej klasy i paru linijek kodu, efekt wydaje się całkiem niezły prawda? ? Mam nadzieję, że przybliżyłem Ci trochę technologię Vaadin, w następnej sekcji opiszę kilka różnic między Vaadinem 7 a Vaadinem 8.
Vaadin 7 i Vaadin 8 – różnice
Vaadin 7 przestał być wspierany w lutym 2019 roku, dlatego powstała potrzeba przepisania istniejących aplikacji napisanych w Vaadinie 7 na Vaadina 8, co wiąże się z poznaniem nowości i usprawnień nowszej wersji tej technologii.
Nowa wersja frameworka idzie w parze wraz z większymi wymaganiami powiązanych technologii. Aby móc pracować z Vaadinem 8, należy korzystać z javy minimum wersji 8 oraz servlet minimum w wersji 3.0. W Vaadinie 8 nastąpiło kilka kluczowych zmian dodających nowe funkcje oraz naprawiające niedoskonałości istniejące w Vaadinie 7. Przedstawię pokrótce kilka problemów występujących w Vaadinie 7, które zostały rozwiązane w Vaadinie 8.
Zmiany w komponencie Grid
Grid jest komponentem odwzorowującym tabelę, Rys. 2.1 przedstawia jego wygląd w aplikacji.
W Vaadinie 7 komponent ten miał kilka braków, które zostały poprawione w Vaadinie 8:
- Brak możliwości dodawania komponentów do komórek grida
W Vaadinie 7 aby tego dokonać trzeba było ingerować w kod front-endowy lub tworzyć specjalne implementacje komponentów w Javie, co znacznie utrudniało wykorzystanie tej funkcji grida. W Vaadinie 8 jest to równie proste co ustawianie zwykłego tekstu.
- Brak możliwości przeciągania wierszy grida do innego grida.
W Vaadinie 7 nie było takiej możliwości, nie jest to funkcjonalność niezbędna, jednak jest to coś nowego, co można wykorzystać w tworzonym systemie.
- Brak możliwości tworzenia struktury drzewiastej w gridzie.
W Vaadinie 8 dodano komponenty Tree i TreeGrid, które dają taką możliwość.
Zmiany w api, upraszczające kod
- Uproszczenie sposobu wyświetlania obiektów javy w komponentach:
Na przykładzie grida – w Vaadinie 7 wymagane było najpierw utworzenie kontenera, który należało wypełnić obiektami a następnie przekazać go do Grida. W Vaadinie 8 obiekty można przekazać bezpośrednio do Grida. Listing 2.2. oraz Listing 2.3. przedstawiają te różnice.
Grid grid = new Grid();
List<MyObject> objects = new ArrayList<>();
BeanItemContainer<MyObject> container = new BeanItemContainer<>(MyObject.class,objects);
grid.setContainerDataSource(container);
Listing 2.2. Dodanie obiektów do Grida w Vaadinie 7
Grid<MyObject> grid = new Grid<>();
List<MyObject> objects = new ArrayList<>();
grid.setItems(objects);
Listing 2.3. Dodanie obiektów do Grida w Vaadinie 8
- Uproszczenie sposobu pobierania wartości z komponentów podczas ich zmiany wartości
W Vaadinie 7 dodając listener wywoływany podczas zmiany wartości np. comoboxa, procedura pobrania nowo ustawionej wartości była nieco wydłużona, należało posłużyć się interfejsem Property, w Vaadinie 8 wartość tą można pobrać bezpośrednio z eventu. Wynika to ze zmiany modelu danych w Vaadinie 8.
ComboBox combobox = new ComboBox();
combobox.addValueChangeListener(event -> {
Property<String> property = event.getProperty();
String value = property.getValue();
System.out.println("Value : " + value);
});
Listing 2.4. Pobranie zmienianej wartości comboboxa w Vaadinie 7
ComboBox<String> combobox = new ComboBox<>();
combobox.addValueChangeListener(event -> {
String value = event.getValue();
System.out.println("Value : " + value);
});
Listing 2.5. Pobranie zmienianej wartości comboboxa w Vaadinie 8
- Uproszenie Lazy loadingu
W Vaadinie 7 w celu otrzymania efektu lazy loading np. w Gridzie, należało utworzyć własną implementację kontenera obsługującego ten przypadek. W Vaadinie 8 zostało to maksymalnie uproszczone. Wystarczy użyć metody Grida setDataProvider() przedstawionej poniżej:
public void setDataProvider(FetchItemsCallback<T> fetchItems, SerializableSupplier<Integer> sizeCallback)
Listing 2.6 Metoda setDataProvider
Interfejs FetchItemsCallback posiada jedną metodę przyjmującą 3 parametry:
- List<QuerySortOrder> – listę określającą sposób sortowania
- Int offset – index początkowy obiektów do pobrania
- Int limit – liczba obiektów do pobrania
Interfejs SerializableSupplier ma za zadanie zwrócić liczbę wszystkich docelowych elementów do wyświetlenia. Poniżej została przykładowa implementacja serwisu, spełniającego oba warunki implementacji interfejsów FetchItemsCallback (metoda findAll()) i SerializableSupplier (metoda count()).
public class MyService {
List<MyObject> data = new ArrayList<>();
public MyService() {
fillData();
}
private void fillData() {
for (int i = 0; i < 100; i++) {
data.add(new MyObject(i));
}
}
public Stream<MyObject> findAll(List sortOrder, int offset, int limit) {
List<MyObject> result = IntStream.range(offset, offset + limit).mapToObj(i -> data.get(i))
.collect(Collectors.toList());
return result.stream();
}
public int count() {
return data.size();
}
}
Listing 2.7. Klasa MyService
Obiekt MyObject – do wyświetlenia w gridzie:
public class MyObject {
private int value;
public MyObject(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
Listing 2.8. Klasa MyObject
MyService service = new MyService();
Grid<MyObject> grid = new Grid<>(MyObject.class);
grid.setDataProvider(service::findAll, service::count);
Listing 2.9. Zastosowanie lazy loading w Gridzie
Oprócz powyższych korzyści, dodatkowym atutem w Vaadinie 8 jest znacznie lepszy performance. Na przykład wyświetlając 100 000 obiektów w gridzie czas generowania takiego grida w starej wersji Vaadina trwał około 233ms a w przypadku Vaadina 8 tylko 9ms, różnica zatem jest bardzo duża. Vaadin 8 posiada także lepszą optymalizację strony klienckiej np. poprzez zastosowanie technologii flexbox, wiąże się to jednak z wsparciem przez nowsze wersje przeglądarek (Firefox minimum wersja 28, Chrome minimum 21), IE tylko częściowo wspiera tą technologię, dlatego nie jest zalecany.
Migracja Vaadina 7 do Vaadina 8
Twórcy Vaadina 8 dostrzegli problem w rozbieżności między Vaadinem 7 a Vaadinem 8, dlatego przygotowali specjalne compatilibity packages, zawierające elementy starego API. W projekcie maven użycie compability packages jest bardzo proste, wystarczy podmienić odpowiednie zależności w pliku pom.xml. Na listingu 3.1 znajduje się zależność wykorzystywana w Vaadinie 7, na listingu 3.2. znajduje się zależność wykorzystywana w Vaadinie 8 przy migracji:
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-server</artifactId>
<version>7.7.6</version>
</dependency>
Listing 3.1. Zależność o artefakcie vaadin-server w Vaadinie 7
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-compatibility-server</artifactId>
<version>8.0.0</version>
</dependency>
Listing 3.2. Zależność o artefakcie vaadin-compatibility-server w Vaadinie 8
Dzięki temu zabiegowi, wszystkie klasy użyte w ramach artefaktu vaadin-server w vaadinie 7, będą mogły zostać użyte po migracji do Vaadina 8. Poniżej spis wszystkich compatibility artefaktów dostępnych w Vaadinie 8:
- vaadin-compatibility-server
- vaadin-compatibility-client
- vaadin-compatibility-client-compiled
- vaadin-compatibility-shared
- vaadin-compatibility-themes
Po podmianie zależności należy pamiętać o zaktualizowaniu importów i widgetsetów, aby nie robić tego ręcznie powstał migration tool – Vaadin Maven plugin może wykonać tą pracę przy użyciu targetu vaadin:upgrade8. Po wykonaniu tej operacji migracja powinna zakończyć się sukcesem. Warto podkreślić, że powyższa migracja pozwala nam użyć Vaadina 7 w Vaadinie 8. Chcąc używać komponentów Vaadina 8 należy przepisać stare komponenty na nowe, niestety jest to nieuniknione gdyż Vaadin 8 stosuje zupełnie inny model danych od Vaadina 7.
Zostaw komentarz