Vaadin – tworzenie frontendu w Spring Boot
Vaadin – tworzenie frontendu w Spring Boot
Vaadin to rozwiązanie/framework które pozwala na tworzenie interfejsu użytkownika w aplikacjach webowych bez konieczności znajomości technologii z rodziny JavaScript takich jak Angular czy React itp. Jeśli jednak jest potrzeba użycia stylów CSS, plików JS to nic nie stoi na przeszkodzie – Vaadin udostępnia programiście taką możliwość. Interfejs graficzny – GUI tworzony jest z użyciem gotowych komponentów dostarczonych przez Vaadina które z kolei za pomocą wybranego layoutu są odpowiednio w nim ustawiane/pozycjonowane. Projektowanie aplikacji przypomina programowanie w bibliotece Swing. Strona projektu Vaadina to http://vaadin.com/. Na stronie producenta Vaadin określany jest w jednym zdaniu jako:
W tym artykule powstanie aplikacja z użyciem Spring Boota i frameworka Vaadin która realizowała będzie zapis na wydarzenie za pomocą przykładowego formularza rejestracyjnego. Ponadto zobaczysz w jaki sposób skonfigurować środowisko Inteliij IDEA, aby bez konieczności restartu całej aplikacji zobaczyć swoje zmiany. Wykorzystamy do tego celu plugin Intellij IDEA – HotSwapAgent. Zaczynamy od nowego projektu Spring Boota – wersja 2.1.7.RELEASE i dodajemy zależności do pliku pom.xml.
dependencyManagement> <dependencies> <dependency> <groupId>com.vaadin</groupId> <artifactId>vaadin-bom</artifactId> <version>14.0.13</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>com.vaadin</groupId> <!-- Replace artifactId with vaadin-core to use only free components --> <artifactId>vaadin</artifactId> <exclusions> <!-- Webjars are only needed when running in Vaadin 13 compatibility mode --> <exclusion> <groupId>com.vaadin.webjar</groupId> <artifactId>*</artifactId> </exclusion> <exclusion> <groupId>org.webjars.bowergithub.insites</groupId> <artifactId>*</artifactId> </exclusion> <exclusion> <groupId>org.webjars.bowergithub.polymer</groupId> <artifactId>*</artifactId> </exclusion> <exclusion> <groupId>org.webjars.bowergithub.polymerelements</groupId> <artifactId>*</artifactId> </exclusion> <exclusion> <groupId>org.webjars.bowergithub.vaadin</groupId> <artifactId>*</artifactId> </exclusion> <exclusion> <groupId>org.webjars.bowergithub.webcomponents</groupId> <artifactId>*</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>com.vaadin</groupId> <artifactId>vaadin-spring-boot-starter</artifactId> <exclusions> <!-- Excluding so that webjars are not included. --> <exclusion><groupId>com.vaadin</groupId> <artifactId>vaadin-core</artifactId></exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>com.vaadin</groupId> <artifactId>vaadin-testbench</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>8</source> <target>8</target> </configuration> </plugin> <plugin> <groupId>com.vaadin</groupId> <artifactId>vaadin-maven-plugin</artifactId> <version>14.0.13</version> <executions> <execution> <goals> <goal>prepare-frontend</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
Tworzymy przykładowy kontroler – należy pamiętać o prawidłowych importach!
import com.vaadin.flow.component.applayout.AppLayout; import com.vaadin.flow.component.applayout.DrawerToggle; import com.vaadin.flow.component.combobox.ComboBox; import com.vaadin.flow.component.html.Image; import com.vaadin.flow.component.html.Label; import com.vaadin.flow.component.orderedlayout.HorizontalLayout; import com.vaadin.flow.component.orderedlayout.VerticalLayout; import com.vaadin.flow.component.tabs.Tab; import com.vaadin.flow.component.tabs.Tabs; import com.vaadin.flow.component.textfield.TextArea; import com.vaadin.flow.router.Route; @Route("app") public class Home extends AppLayout { public Home() { Image img = new Image("http://i.imgur.com/GPpnszs.png", "Vaadin Logo"); img.setHeight("44px"); addToNavbar(new DrawerToggle(), img); Tabs tabs = new Tabs(new Tab("Home"), new Tab("About")); tabs.setOrientation(Tabs.Orientation.VERTICAL); addToDrawer(tabs); } }
po uruchomieniu aplikacji może zdarzyć się, że wystąpi następujący błąd:
java.lang.runtimeexception: unable to initialize vaadin devmodehandler
wtedy należy:
- sprawdzić czy zmienna środowiskowa która wskazuje na lokalizację mavena jest prawidłowo ustawiona,
- w katalogu projektu wykonać komendę która pozwoli na zainstalowanie menadżera pakietów npm.
mvn com.github.eirslett:frontend-maven-plugin:1.7.6:install-node-and-npm -DnodeVersion="v12.13.0
po prawidłowym uruchomieniu aplikacji i po wejściu na adres:
http://localhost:8080/
otrzymamy wynik:
Przechodzimy zatem na jedyny dostępny adres:
http://localhost:8080/app
w wyniku otrzymujemy:
Zanim zaczniemy projektować formularz rejestracyjny warto skonfigurować sobie środowisko Intellij IDEA w taki sposób, aby nie trzeba było za każdym razem po wprowadzeniu zmiany restartować Spring Boota. Znacznie przyspieszy to pracę nad aplikacją. Konfigurację przeprowadzimy w trzech prostych krokach:
krok 1
- Instalacja pluginu HotSwapAgent:
Z poziomu Intellij IDEA należy zainstalować plugin HotSwapAgent:
krok 2
- Konfiguracja pluginu HotSwapAgent:
pobranie pliku hotswap-agent-1.0.jar ze strony:
http://github.com/HotswapProjects/HotswapAgent/releases
wskazanie lokalizacji do pobranego pliku w konfiguracji pluginu:
pobranie pliku DCEVM-8u181-installer-build2.jar ze strony:
http://github.com/dcevm/dcevm/releases
należy wybrać katalog z JDK – wersja 8 i zainstalować narzędzie.
krok 3
- Autoprzeładowanie klas po kompilacji:
Utwórzmy kontroler który wykorzystuje następujące kontrolki Vaadina:
- TextField,
- ComboBox,
- Button,
- Dialog.
więcej kontrolek znajdziesz na stronie: http://vaadin.com/components
import com.vaadin.flow.component.applayout.AppLayout; import com.vaadin.flow.component.applayout.DrawerToggle; import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.combobox.ComboBox; import com.vaadin.flow.component.dialog.Dialog; import com.vaadin.flow.component.html.Image; import com.vaadin.flow.component.html.Label; import com.vaadin.flow.component.orderedlayout.HorizontalLayout; import com.vaadin.flow.component.orderedlayout.VerticalLayout; import com.vaadin.flow.component.tabs.Tab; import com.vaadin.flow.component.tabs.Tabs; import com.vaadin.flow.component.textfield.TextField; import com.vaadin.flow.router.Route; @Route("app") public class Home extends AppLayout { TextField textArea = new TextField("Rejestracja na wydarzenie"); ComboBox<String> comboBox = new ComboBox<>("Wydarzenia"); public Home() { Image img = new Image("http://i.imgur.com/GPpnszs.png", "Vaadin Logo"); img.setHeight("44px"); addToNavbar(new DrawerToggle(), img); Tabs tabs = new Tabs(new Tab("Home"), new Tab("About")); tabs.setOrientation(Tabs.Orientation.VERTICAL); addToDrawer(tabs); HorizontalLayout horizontalLayout = new HorizontalLayout(); horizontalLayout.add(getLayoutTextBoxComboBox()); setContent(horizontalLayout); } private HorizontalLayout getLayoutTextBoxComboBox() { HorizontalLayout horizontalLayout = new HorizontalLayout(); horizontalLayout.add(getTextBoxLayout()); horizontalLayout.add(getComboBoxLayout()); return horizontalLayout; } private VerticalLayout getTextBoxLayout() { VerticalLayout vertical = new VerticalLayout(); Label label = new Label(); textArea.setPlaceholder("adres email"); textArea.addValueChangeListener(event -> { if (event.getSource().isEmpty()) { label.setText(" nic nie wybrano"); } else { label.setText("[wybrano] " + event.getValue()); } }); vertical.add(textArea); vertical.add(label); vertical.add(getSaveButton()); return vertical; } private VerticalLayout getComboBoxLayout() { VerticalLayout vertical = new VerticalLayout(); Label label = new Label(); comboBox.setWidthFull(); comboBox.setItems("Spring Boot", "konferencja GIT", "webinar Java 8"); comboBox.addValueChangeListener(event -> { if (event.getSource().isEmpty()) { label.setText(" nic nie wybrano"); } else { label.setText("[wybrano] " + event.getValue()); } }); vertical.add(comboBox); vertical.add(label); return vertical; } private Button getSaveButton() { final Button button = new Button("zapisz się!", event -> { Dialog dialog = new Dialog(); dialog.add(new Label("podsumowanie zapisu na wydarzenie")); VerticalLayout verticalLayout = new VerticalLayout(); verticalLayout.add(new Label("[email] " + textArea.getValue())); verticalLayout.add(new Label("[wydarzenie] " + comboBox.getValue())); dialog.add(verticalLayout); dialog.setWidth("400px"); dialog.setHeight("150px"); dialog.open(); }); return button; } }
po wejściu na adres:
http://localhost:8088/app
otrzymamy wynikową aplikację!
Aby przetestować czy aktualizacja projektu bez konieczności restartu Spring Boota działa prawidłowo należy uruchomić aplikację w trybie Debuggera:
następnie wprowadzić zmiany do przykładowej klasy i przekompilować klasę:
aplikacja powinna się odświerzyć oraz powinien wyskoczyć komunikat, że klasa została przeładowana:
Leave a comment