CodeGym /Kursy /Spring Boot /Gradle Wrapper, Toolchain i Boot plugin

Gradle Wrapper, Toolchain i Boot plugin

Spring Boot
Poziom 3, Lekcja 1
Dostępny

1. Budowanie jako część aplikacji

Jeśli dopiero przyszedłeś ze świata programów konsolowych, budowanie może wydawać się czymś w rodzaju „no to po prostu nacisnąć Run". Ale jak tylko projekt ma choćby jednego kolegę (lub drugi komputer), zaczyna się klasyczny serial: „u mnie działa, u ciebie nie, chodź na call, pokaż ekran". Spring Boot jako platforma lubi przewidywalność, a to wymaga też przewidywalnego budowania.

Szkielet projektu już jest, ale bez wyraźnych reguł budowania pozostaje po prostu zestawem plików. Po generacji główne pytanie staje się bardzo praktyczne: jak sprawić, żeby ten szkielet jednakowo składał się i uruchamiał na każdej maszynie.

Wyobraź sobie, że catalog-service to danie. Kod – składniki, kontener Spring – kuchnia, a budowanie – przepis z temperaturą, czasem i dokładnymi proporcjami. Jeśli przepis jest „orientacyjny", to na jednej płycie wyjdzie normalnie, a na drugiej – węgiel. Dlatego na starcie ustalamy trzy rzeczy: jaki Gradle jest używany, jaka Java jest używana i jakie zadania Boot są dostępne w projekcie.

Żeby nie mylić terminów, trzymaj w głowie prostą tabelę – bardzo oszczędza nerwów:

Rzecz Co ustala Gdzie mieszka Jak uruchamiasz/używasz
Gradle Wrapper Wersję Gradle Wewnątrz repozytorium projektu ./gradlew ...
Java Toolchain Wersję Java do kompilacji i zadań Gradle build.gradle.kts Gradle stosuje automatycznie
Boot plugin Zadania i konwencje zorientowane na Boot build.gradle.kts bootRun,
bootJar
i inne

Te trzy punkty potem zbiegają się w jednym miejscu – w build.gradle.kts. Dlatego użyteczne jest najpierw zrozumienie ich ról osobno, a dopiero potem czytanie pliku build w całości. Właśnie dlatego teraz ważne jest nie tyle naciśnięcie Run, ile zrozumienie, na czym to uruchomienie w ogóle się opiera.

2. Gradle Wrapper: „Gradle, który przychodzi razem z projektem"

W idealnym świecie wszyscy mają taki sam Gradle, taką samą Javę i takie same szczęście. W realnym – każdy deweloper na laptopie ma swój „zoo": u kogoś Gradle 8, u kogoś 9.4, ktoś w ogóle go nie instalował, bo „IntelliJ u mnie samo wszystko umie". Gradle Wrapper to sposób na uniezależnienie projektu od tych przypadłości.

Wrapper to nie oddzielny program „zamiast Gradle". To zestaw plików w twoim projekcie, który gwarantuje: gdy uruchamiasz budowanie, uruchamiasz właściwą wersję Gradle, wybraną przez sam projekt. I tak, właśnie dlatego w projektach Boot przyjęto pisać w README komendy z ./gradlew, a nie po prostu gradle.

Gdy generujesz projekt w Initializr, dodaje on Wrapper automatycznie – i to świetnie, bo ręcznie początkujący prawie zawsze coś zapomni, a potem powie: „Gradle mi się zepsuł", choć w rzeczywistości go… nie było.

Mini-mapa plików Wrapper wygląda tak:

catalog-service/
├── gradlew
├── gradlew.bat
└── gradle/
    └── wrapper/
        ├── gradle-wrapper.properties
        └── gradle-wrapper.jar

Tu ważne jest bez mistyki rozumieć rolę każdego pliku. gradlew – skrypt dla Linux/macOS, gradlew.bat – dla Windows. Ich zadanie jest proste: wziąć ustawienia z gradle-wrapper.properties, pobrać potrzebny Gradle jeśli nie ma go jeszcze w cache, i uruchomić budowanie. gradle-wrapper.jar to małki „silnik" Wrappera, który potrafi pobierać i uruchamiać właściwą wersję Gradle.

Jeśli myślisz „a można usunąć gradle-wrapper.jar, bo to binarny, dziwnie trzymać w git?" – można, ale wtedy wracasz do epoki kamienia: każdy będzie uruchamiał budowanie jak wyjdzie. Tak nie robimy. Chcemy, żeby catalog-service był przenośny.

Jak Wrapper wybiera Gradle

Najbardziej interesujący tu plik – gradle/wrapper/gradle-wrapper.properties. Jest mały, ale to właśnie on odpowiada za to, jaką wersję Gradle uważa za „właściwą" twój projekt.

Typowy przykład:

# Skąd Wrapper pobiera dystrybucję Gradle
distributionUrl=https\://services.gradle.org/distributions/gradle-9.4-bin.zip

Zwróć uwagę na prostą myśl: wersja Gradle to nie „co masz zainstalowane", a „co jest zapisane w projekcie". Przy pierwszym uruchomieniu Wrapper pobierze wskazaną kompilację Gradle i umieści ją w cache użytkownika, zwykle gdzieś w katalogu domowym, wewnątrz ~/.gradle/.... Dlatego pierwsze uruchomienie może trwać trochę dłużej: to normalne, nie zepsuło ci internetu.

Użyteczne jest z góry wiedzieć, gdzie mieszka cache, żeby nie panikować, gdy Gradle „długo coś pobiera". Uproszczony obraz jest taki:

flowchart TD
    A[Uruchamiasz ./gradlew] --> B[Wrapper czyta gradle-wrapper.properties]
    B --> C{Potrzebna wersja Gradle jest już w cache?}
    C -- Tak --> D[Uruchomienie Gradle]
    C -- Nie --> E[Pobieranie gradle-9.4-bin.zip]
    E --> F[Rozpakowywanie do ~/.gradle/wrapper/dists]
    F --> D[Uruchomienie Gradle]

I to jest właśnie „odtwarzalność": ten sam projekt zawsze pobiera tę samą wersję Gradle, i budowanie zachowuje się przewidywalnie.

Prawidłowe uruchamianie Wrappera z korzenia

Wrapper uruchamia się komendami, które wyglądają tak samo na wszystkich maszynach, ale z małą różnicą po OS. Ważna reguła – uruchamiać je z korzenia projektu, tam gdzie leży gradlew. Inaczej Gradle może nie znaleźć twojego build.gradle.kts, settings.gradle.kts i w ogóle będzie się zachowywać, jakbyś „przyszedł nie na tę imprezę".

Mini-zestaw komend, które warto zapamiętać już teraz:

# Linux/macOS
./gradlew --version

# Windows (cmd)
gradlew.bat --version

# Windows (PowerShell)
.\gradlew --version

Zwróć uwagę: ./gradlew to nie „jakaś magiczna kropka i ukośnik". To dosłownie „uruchom plik gradlew z bieżącego folderu". Jeśli przypadkowo napiszesz po prostu gradle, uruchomisz globalnie zainstalowanego Gradle, jeśli go masz, i cała idea Wrappera zostanie zniszczona jednym naciśnięciem Enter. Więc tak, ./gradlew to nasz mały codzienny rytuał, który ratuje od dużych codziennych problemów.

3. Java Toolchain: ustalamy wersję Java

Drugi klasyczny ból początkującego: „Zainstalowałem Javę, ale projekt nadal się nie składa" lub „Mam Java 25, a Gradle pisze, że potrzeba 21". I tu ważne jest zrozumienie: w rzeczywistości możesz mieć kilka Jav jednocześnie, i to nie błąd, a normalne środowisko pracy. Problem zaczyna się, gdy projekt nie mówi jawnie, jakiej dokładnie Javy oczekuje.

Java Toolchain to mechanizm Gradle, który pozwala w build.gradle.kts jawnie powiedzieć: „kompiluj projekt tą wersją Javy". I wtedy budowanie przestaje zależeć od tego, jaka Java „przypadkowo okazała się pierwsza w PATH" lub którą Javę IDE podchwyciło „domyślnie".

Tu ważne jest trzymanie jednej linii: projekt nie powinien nagle mieć drugiej „prawdziwej" wersji Javy. Jeśli w Initializr wybrano Java 25, tę samą wersję ustalamy też w toolchain. Wtedy projekt nie będzie miał oddzielnej „formalnej" Javy w formularzu i oddzielnej „prawdziwej" Javy w budowaniu.

Minimalne ustawienie toolchain w build.gradle.kts

Toolchain konfiguruje się w build.gradle.kts w bloku java. Wygląda spokojnie i nie wymaga magii:

java {
    toolchain {
        // Jawnie ustalamy wersję JDK do budowania (kompilacji i zadań Gradle)
        languageVersion = JavaLanguageVersion.of(25)
    }
}

Co to oznacza po ludzku: „Gradle, gdy będziesz kompilował i uruchamiał zadania, używaj JDK 25 jako docelowego". Przy tym na maszynie może być i JDK 17, i 21, i 25, ale budowanie będzie starać się używać dokładnie tego, co wskazałeś.

Ważne jest, żeby nie mylić tego z tym, na jakiej Javie uruchamia się sam Gradle. Gradle też działa wewnątrz JVM. Jeśli masz zupełnie nieodpowiednią Javę do uruchomienia Gradle, możesz dostać błąd jeszcze zanim toolchain zacznie działać. To rzadkość, ale jeśli się wydarzy – nie trzeba panikować: to nie „Spring się zepsuł", a po prostu „Gradle nie mógł startować na tej JVM".

Weryfikacja zastosowania toolchain

Początkujący często robią ustawienie toolchain, a potem nie rozumieją: „W ogóle zadziałało, czy po prostu ładnie napisałem kawałek tekstu w build.gradle.kts?" Dobra wiadomość: weryfikacja istnieje, i nie wymaga filozofii.

Po pierwsze, można spojrzeć, jaką Javę widzi Gradle i na jakiej w ogóle wystartował:

./gradlew --version

Po drugie, w Gradle jest raport po toolchainach, często dostępny jako zadanie javaToolchains. To wygodny sposób na zobaczenie, jakie JDK zostały znalezione i który zostanie wybrany:

./gradlew -q javaToolchains

Jeśli zadanie jest niedostępne, to nie katastrofa: wtedy wystarczy ./gradlew --version i sprawdzenie ustawień IDE. Ale gdy javaToolchains jest, to bezpośredni „rentgen" twojej części Javy w budowaniu.

Tu użyteczne jest trzymanie prostej myśli: toolchain dotyczy budowania, a nie tego, co przypadkowo widzisz w terminalu po java -version. Terminal pokazuje „domyślną Javę użytkownika", a Gradle toolchain – „Javę wybraną przez projekt".

4. Plugin org.springframework.boot: rola w budowaniu

Jeśli Wrapper i toolchain odpowiadają za odtwarzalność budowania, to Boot plugin odpowiada za to, żeby było zorientowane na Spring Boot. Można złożyć projekt Java i bez Boot plugin. Można nawet złożyć aplikację webową i bez niego, jeśli bardzo chcesz cierpieć. Ale my tu uczymy się nie cierpieć, a budować właściwy baseline.

Boot plugin to nie „jeszcze jedna zależność". To rozszerzenie Gradle, które dodaje wygodne zadania i konwencje właśnie dla aplikacji Boot: uruchomienie przez bootRun, składanie wykonywalnego jar przez bootJar, właściwe pakowanie, sensowne defaults. Jakby mówisz Gradle: „To nie jest tylko program Java. To aplikacja Spring Boot, bądź łaskawy traktować ją odpowiednio".

Podłączamy Boot plugin i ustalamy wersję Boot

Pluginy podłącza się w bloku plugins w build.gradle.kts. Minimalne wygląda tak:

plugins {
    // Podstawowe zadania projektu Java: kompilacja, testy, składanie jar
    java

    // Zadania i konwencje Spring Boot: bootRun, bootJar itd.
    id("org.springframework.boot") version "4.0.3"
}

Sens jest prosty: java mówi Gradle „to jest projekt Java, włącz kompilację, testy i standardowe zadania", a org.springframework.boot dodaje ponad tym Boot-specyfikę. Wersja pluginu zazwyczaj pokrywa się z wersją Spring Boot, którą wybrałeś w Initializr.

I ważna praktyczna myśl: nie trzeba „podkręcać wersji Boot na oko". Jeśli nagle zmienisz 4.0.3 na coś w stylu 4.0.99-rc1, bo „chcę najnowsze", dostaniesz przygodę. A przygody w tym kursie potrzebne są ściśle w postaci rozumienia, a nie w postaci bugów.

Co dodaje Boot plugin

Często wydaje się, że plugin to coś abstrakcyjnego. Dlatego utrwalmy maksymalnie konkretnie: Boot plugin dodaje zadania Gradle, z których naprawdę będziesz korzystać.

Task Do czego potrzebny Co dostaniesz w rezultacie
bootRun Uruchomienie aplikacji Boot ze źródeł Aplikacja startuje bez ręcznego java -cp ...
bootJar Składanie wykonywalnego jar Boot Gotowy artefakt, który można uruchomić
test Uruchomienie testów Sprawdzenie, że projekt przynajmniej się składa i testy przechodzą

Jak zobaczyć, że zadanie istnieje, nie uruchamiając go? Na przykład tak:

./gradlew help --task bootRun

Jeśli Gradle opisał ci zadanie bootRun, znaczy to, że Boot plugin jest podłączony i działa. To bardzo spokojna, „bezstresowa" weryfikacja: nic nie składasz, nic nie uruchamiasz, a po prostu pytasz Gradle: „czy w ogóle mamy taki przycisk?"

5. Ogólny schemat baseline budowania

Na początku drogi łatwo postrzegać gradlew, toolchain i Boot plugin jako trzy oderwane zaklęcia. Ale to w istocie jedna historia: sprawić, żeby budowanie było przewidywalne. Użyteczne jest zobaczenie całego konwejera w całości, bo inaczej będziesz naprawiać błędy w ciemno i mówić sławne: „nic nie zmieniałem, samo".

Spróbujmy złożyć to w jeden schemat, jak w dokumentach inżynierskich:

flowchart TD
    Dev[Deweloper] -->|uruchamia| W["./gradlew"]
    W --> G[Gradle 9.4 z Wrappera]
    G --> P[Plugins: java + org.springframework.boot]
    P --> T[Tasks: compileJava / test / bootRun / bootJar]
    T --> A[Uruchomienie lub składanie catalog-service]

Tu wszystko jest uczciwe i bez mistyki. Uruchamiasz ./gradlew – to wejście do budowania. Wrapper zapewnia wersję Gradle. Gradle czyta build.gradle.kts, podłącza pluginy. Pluginy dodają zadania. Zadania albo uruchamiają aplikację (bootRun), albo składają artefakt (bootJar). I dopiero po tym pojawia się coś, co można nazwać „działającą aplikacją".

Jeśli zapamiętać ten łańcuch, połowa wczesnych problemów znika sama: rozumiesz, na którym kroku „się zepsuło", i przestajesz naprawiać wszystko po kolei.

Mini-weryfikacja baseline w catalog-service

Bardzo chce się od razu nacisnąć Run i zobaczyć „Started CatalogServiceApplication…". To normalne, wszyscy tacy jesteśmy. Ale dobry start inżynierski – najpierw upewnić się, że narzędzia są na miejscu, a potem dopiero uruchamiać. Tu zrobimy małą weryfikację: zajmuje parę minut i oszczędza godziny.

Pierwsza komenda sprawdza, że Wrapper działa i Gradle uruchamia się „przez projekt":

./gradlew --version

Druga komenda jest użyteczna właśnie dla tematu dzisiejszego wykładu: zobaczysz, jakie Java toolchainy są dostępne, lub przynajmniej upewnisz się, że Gradle normalnie widzi twoją Javę:

./gradlew -q javaToolchains

Trzecia komenda weryfikuje Boot plugin „bez ryzyka": nie startujemy serwera i nic nie pobieramy ponad konieczne – po prostu sprawdzamy, że zadanie jest:

./gradlew help --task bootRun

Jeśli wszystkie trzy komendy zadziałały bez błędów, jesteś w bardzo dobrej pozycji. Masz odtwarzalne budowanie, ustaloną docelową Javę i zadania zorientowane na Boot. To właśnie podstawowa higiena budowania projektu.

6. Typowe błędy

Prawie wszystkie problemy z Wrapperem, toolchain i pluginami pojawiają się nie dlatego, że „coś nie zrozumiałeś", ale dlatego, że wszyscy mamy nawyki z innych środowisk. Ktoś przyzwyczaił się, że „IDE samo złoży", ktoś – że java -version pokazuje prawdę, ktoś – że „zbędne pliki można usunąć". Przeanalizujmy najczęstsze pułapki, żebyś rozpoznawał je od pierwszego spojrzenia.

Błąd nr 1: uruchamiać gradle zamiast ./gradlew.
Jeśli uruchamiasz globalnego gradle, wychodzisz ze świata odtwarzalności. Możesz mieć Gradle innej wersji i dostać dziwne błędy: od niekompatybilności pluginów do „dlaczego nie mam bootRun". Leczy się bardzo prosto: w projektach kursu zawsze zaczynamy komendy od ./gradlew (lub .\gradlew w PowerShell).

Błąd nr 2: uruchamiać Wrapper nie z korzenia projektu.
Gdy uruchamiasz komendy z innego folderu, Gradle może nie znaleźć build.gradle.kts i settings.gradle.kts lub znaleźć „nie ten projekt". Objawy bywają zabawne: od „Task not found" do poczucia, że Gradle „nie widzi zależności". Nawyk prosty: najpierw cd catalog-service, potem ./gradlew ....

Błąd nr 3: usuwać pliki Wrappera, bo „śmieci" lub „binarne w git – źle".
gradlew, gradlew.bat, gradle-wrapper.jar, gradle-wrapper.properties to nie śmieci, a część projektu. Jeśli je usuniesz, zamieniasz budowanie w loterię. W projekcie edukacyjnym chcemy, żeby każda osoba mogła sklonować repozytorium i złożyć je bez ręcznej instalacji „właściwego Gradle".

Błąd nr 4: mylić „Javę w terminalu" i „Javę, której używa budowanie".
Komenda java -version pokazuje, jaka Java jest pierwsza w PATH w twoim bieżącym terminalu. Ale Gradle toolchain może wybierać inną Javę. To nie bug i nie spisek – wręcz przeciwnie, to mechanizm kontroli. Jeśli widzisz niezgodność, nie przerażaj się: sprawdzaj ./gradlew --version i, jeśli dostępne, javaToolchains.

Błąd nr 5: nie ustalać Java Toolchain i polegać na szczęściu IDE.
Dziś się złożyło, jutro zaktualizowałeś IDE, pojutrze kolega ma inne JDK – i wszystko pojechało. Toolchain nie jest potrzebny dlatego, że „nie ufasz sobie", a dlatego, że projekt powinien mieć wyraźny kontrakt co do Javy. Dla projektu Boot to podstawowa higiena, jak mycie rąk przed gotowaniem.

1
Zadanie
Spring Boot, poziom 3, lekcja 1
Niedostępne
Wrapper, Boot plugin i Java Toolchain w jednym projekcie
Wrapper, Boot plugin i Java Toolchain w jednym projekcie
1
Zadanie
Spring Boot, poziom 3, lekcja 1
Niedostępne
Skrypt raportu o środowisku build
Skrypt raportu o środowisku build
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION