Lipiec 27, 2019

Jak stworzyć projekt w Spring Boot?

Spring Boot

W poprzednim artykule na temat Springa i Spring Boota wspomniałem, że SB został stworzony w celu ułatwienia życia programistom.

Dzięki Spring Bootowi jesteśmy w stanie w kilka minut stworzyć projekt, nie martwiąc się dużymi ilościami konfiguracji – tak jak miało to miejsce bezpośrednio w Springu.

Budując aplikację w Spring Boocie mamy też możliwość szybkiego uruchomienia aplikacji bez konieczności uruchamiania dedykowanego serwera aplikacji np. Tomcata i wrzucania na niego ręcznie pliku wynikowego WAR.

Wszystko to dzieje się automagicznie, co pokażę Ci w tym artykule.

Tworzenie projektu

Teraz krok po kroku stworzymy nowy projekt Spring Bootowy, a na sam koniec go uruchomimy.

Wygenerować projekt SB możemy na dwa sposoby:

My skorzystamy z pierwszej opcji, a więc wchodzimy pod ten adres i naszym oczom powinien ukazać się taki widok.

1. Narzędzie do budowania aplikacji

Spring Initializr umożliwia wygenerowanie dwóch typów projektu:

  • Maven;
  • Gradle.

Tak naprawdę wybór narzędzia należy do Ciebie, ja osobiście korzystam z Mavena dlatego też go wybieram.

2. Język

Spring umożliwia pisanie aplikacji w kilku językach JVM:

  • Java;
  • Kotlin;
  • Groovy.

Ja bez zastanowienia wybieram Javę, ponieważ innych języków nie znam na wystarczającym poziomie.

Jeśli jednak czujesz się lepiej w innym języku to nic nie stoi na przeszkodzie, abyś go wybrał.

3. Wersja

Mamy do wyboru kilka wersji Spring Boot, ja wybiorę 2.6.1.

4. Metadata

Kolejnym krokiem jest wybór podstawowych informacji o projekcie. Rozwiń sekcję Options w sekcji Project Metadata, twoim oczom powinnien pojawić się taki widok:

Musimy zdefiniować:

  • Group – jest to często domena firmy, w której jest tworzony projekt;
  • Artifact – nazwa konkretnego modułu;
  • Packaging – jaki plik wynikowy chcemy otrzymać;
  • Java – wersja Javy, w której będziemy pisać naszą aplikację.

Ja uzupełniłem pola w ten sposób:

5. Zależności

Następnym krokiem jest wybór zależności, które mają być automatycznie dodane do naszego projektu.

Ten krok może zostać pominięty, po prostu w przyszłości sami musielibyśmy dodawać nowe zależności do pliku pom.xml.

Możesz teraz zobaczyć ile modułów udostępnia nam Spring, jak bardzo ułatwia nam pracę przy developmencie.

Oczywiście wybierzemy sobie kilka z nich:

  • Spring WEB Starter – jest to zależność umożliwiająca tworzenie aplikacji webowych, wystawiania restowy kontrolerów oraz zawiera w sobie wbudowany serwer Tomcat;
  • Lombok – generuje za nas sporo kodu (o tym później);
  • Thymeleaf – engine template, czyli dynamiczne tworzenie widoków we wzorcu projektowym MVC;
  • Spring Data JPA – umożliwia prostsze interakcje z bazą danych;
  • H2 Database – baza danych in-memory

Dodając te zależności do projektu, Spring Boot zapewni im domyślną konfigurację. Nie będziemy musieli marnować czasu na konfiguracje np. bazy danych, możemy od razu zacząć development.

6. Generowanie

Na koniec zostało już nam tylko wygenerować projekt, powinniśmy na dysku mieć plik zip – u mnie jest to camel.zip.

Uruchomienie projektu

Po wygenerowaniu i pobraniu projektu czas go uruchomić.

Archiwum zip wystarczy rozpakować, a projekt otworzyć w Twoim IDE – u mnie jest to IntelliJ Idea.

Po otworzeniu projektu, w moim przypadku IntelliJ automatycznie zaczął pobierać zależności zawarte w pliku pom.xml. Po chwili wszystkie zależności powinny być już dostępne w lokalnym repozytorium Maven.

Gdy cały projekt otworzy się poprawnie, rozwińmy sobie drzewo projektu.

Znajdziemy w nim jedną klasę – w moim przypadku jest to CamelApplication.

Otwórzmy ją i spójrzmy na jej zawartość.

Jak widać nie dzieje się tutaj dużo, mamy tutaj metodę main, w niej wywołujemy statyczną metodę run oraz mamy adnotację @SpringBootApplication. Omówmy sobie po kolei za co one są odpowiedzialne.

  • @SpringBootApplication – adnotacja mówi Springowi, aby podczas startu aplikacji wczytała domyślną konfigurację oraz przeskanowała komponenty (o tym w następnym artykule)
  • SpringApplication.run – uruchamia całą aplikację Spring, podnosząc jej cały kontekst

Przejdźmy jeszcze na chwilę do pliku pom.xml, abyś wiedział co się dzieje w całym projekcie.

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.1.6.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>pl.blog.spring</groupId>
	<artifactId>camel</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>camel</name>
	<description>Camel management application</description>

Na początku mamy podstawowe informacje o projekcie, oraz definiujemy rodzica projektu – w naszym przypadku spring-boot-starter-patern, dzięki któremu nie mamy duplikacji zależności Springowych (są to już mechanizmy wbudowane w Maven)

<properties>
		<java.version>1.8</java.version>
</properties>

Następnie jest zdefiniowana wersja Javy dla projektu.

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>com.h2database</groupId>
			<artifactId>h2</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

Następnie mamy zdefiniowane zależności, z których możemy korzystać w naszym projekcie.

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

Na koniec jest zdefiniowane użycie plugin spring-boot-maven-plugin podczas budowania projektu.

W dokumentacji możemy wyczytać:

The Spring Boot Maven Plugin provides Spring Boot support in Maven, letting you package executable jar or war archives and run an application “in-place”.

Plugin ten, więc ogarnia za nas budowanie wykonywalnego JARA lub WARA i natychmiastowego uruchomienia aplikacji, bez konieczności ogarniania dedykowanego serwera aplikacji.

Jeśli wszystko mamy już opanowane to czas na uruchomienie projektu, wystarczy zrobić Run na klasie z metodą main.

Po uruchomieniu aplikacji w konsoli powinny pojawić Ci się logi jak na powyższym obrazku. Są to logi, z których możemy wyczytać co Spring inicjalizuje w aplikacji oraz jaką konfigurację wczytuje.

2019-07-27 13:04:30.451  WARN 18540 --- [           main] ion$DefaultTemplateResolverConfiguration : Cannot find template location: classpath:/templates/ (please add some templates or check your Thymeleaf configuration)

W jednym z tych logów możemy znaleźć ostrzeżenie, że Spring nie znalazł lokalizacji templatek dla Thymeleafa. Takie ostrzeżenie lub inne error okazują się pomocne, gdy coś nie działa w naszej aplikacji.

Jednak dla nas najbardziej interesującym logiem jest:

2019-07-27 13:04:30.581  INFO 18540 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2019-07-27 13:04:30.583  INFO 18540 --- [           main] pl.blog.spring.camel.CamelApplication    : Started CamelApplication in 3.722 seconds (JVM running for 5.031)

Mamy teraz pewność, że Tomcat został uruchomiony na porcie 8080, a cała aplikacja wstała w czasie 3.7s.

Skoro wstała, to może da się to jakoś sprawdzić? Wejdźmy na adres:

localhost:8080

Naszym oczom powinien ukazać isę taki widok:

Oznacza to, że serwer działa, ale nie jest w stanie znaleźć pod tym adresem żadnego zasobu (404 – Not Found).

Potencjalny błąd

Jeśli Twoja aplikacja nie uruchomiła się poprawnie, a Twoje logi wskazują podobne informację jak poniżej:

***************************
APPLICATION FAILED TO START
***************************

Description:

The Tomcat connector configured to listen on port 8080 failed to start. The port may already be in use or the connector may be misconfigured.

Action:

Verify the connector's configuration, identify and stop any process that's listening on port 8080, or configure this application to listen on another port.

Oznacza to, że port 8080 jest aktualnie zajęty przez inną usługę na komputerze, więc mamy dwa rozwiązania:

  • wyłączyć tamtą usługę;
  • zmienić port naszej aplikacji.

O ile to pierwsze jesteś w stanie sam zrobić, to pokażę Ci jak skonfigurować samemu port naszej aplikacji.

Otwórz plik application.properties, który znajdziesz w katalogu

\src\main\resources

I dopisz do niego poniższą linię:

server.port=8090

Plik application properties jest plikiem konfiguracyjnym, który jest wczytywany podczas startu aplikacji. Umożliwia on zmianę konfiguracji zależnie np. od środowiska w jakim jesteśmy (testowy/produkcyjny).

Więcej o tym pliku dowiesz się w następnych artykułach.

Po ponownym uruchomieniu aplikacji, Twój serwer powinien zostać wystawiony pod adresem:

localhost:8090

Release aplikacji

W przypadku, gdy skończyliśmy development naszej aplikacji bardzo prawdopodobne jest, że będziemy chcieli się nią pochwalić i np. uruchomić na VPS.

Aby zbudować aplikację w katalogu projektu w konsoli wystarczy wpisać polecenie:

mvn install

Po pomyślnym przejściu całego procesu budowania projektu w folder /target powinien Ci się pojawić plik z roszerzenie JAR.

Możesz go teraz uruchomić wszędzie, wystarczy, że masz tam zainstalowany JRE. Zrobisz to poleceniem:

java -jar .jar

Podsumowanie

Pokazałem Ci jak przebiega cały proces tworzenia projektu przy użyciu Spring Initialzra, jak wygląda drzewo takiego projektu oraz jak na koniec można zbudować taki projekt.

Z taką podstawową wiedzą jesteś już w stanie stworzyć projekt oraz uruchomić go na dowolnym serwerze, na którym jest zainstalowany JRE.

Jednak to dopiero początek drogi, w następnych artykułach pokażę Ci jak rozszerzać naszą aplikację o nowe funkcjonalności.