Software Development

Vaadin – różnice między wersją 7 a 8

Czerwiec 28, 2019 0
Podziel się:

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

rys1.1 - Vaadin - różnice między wersją 7 a 8

Rys. 1.1 Podstawowy projekt w Vaadinie

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.

rys 1.3 300x219 - Vaadin - różnice między wersją 7 a 8

Rys 1.3 Uruchomiona aplikacja w przeglądarce

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.

rys. 2.1 - Vaadin - różnice między wersją 7 a 8

Rys. 2.1. Przykładowy Grid

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

Oraz zastosowanie w gridzie:

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.

4.4 / 5
Krzysztof Krocz
Autor: Krzysztof Krocz
Java Developer w Sii Polska od 2017 roku. Na co dzień pracuję m.in. w technologiach Vaadin, Hibernate, EJB, Docker.

Imię i nazwisko (wymagane)

Adres email (wymagane)

Temat

Treść wiadomości

Zostaw komentarz