Ako začať
Keď neviete, čo je Gradle, odbehnite ku veselému motivačnému textu na blogu SoftWare Samuraja. Aby sme po ňom neopakovali, poznamenáme, že Gradle je niečo ako Maven, čiže nástroj na automatizáciu zostavovania projektov, lež miesto XML používate prehľadnejšie konštrukcie jazyka Groovy.
Ukážeme si, ako možno veľmi jednoducho naštartovať miniprojekt, kde vytvoríme požadovanú adresárovú štruktúru, zavedieme závislosti, projekt spustíme a naučíme sa, ako vytvoriť ZIP verziu s vydanou verziou.
Aby sme sa nezatatárili s HTTP servletmi a spol., na webovú časť využijeme mikroframework Spark.
Stiahnutie a inštalácia
Stiahnutie
Z webu Gradle stiahneme ZIP súbor s binárkami. Použijeme verziu 1.7-rc1, ktorá je síce release candidate, teda nefinálna verzia, ale až od tejto verzie sú k dispozícii nástroje pre rýchle naštartovanie projektu.
Rozbalenie
Súbor rozbalíme do vhodného adresára: napr. C:\java\gradle-1.7-rc-1-bin.zip
.
Premenná PATH
Cestu pridáme do premennej prostredia PATH
, aby sme mohli volať gradle
z ľubovoľného adresára.
set PATH=%PATH%;C:\java\gradle-1.7-rc-1\bin
Overíme funkčnosť
Z ľubovoľného adresára spusťme gradle -v
.
c:\Projects>gradle -v
------------------------------------------------------------
Gradle 1.7-rc-1
------------------------------------------------------------
Build time: 2013-07-02 14:56:30 UTC
Build number: none
Revision: 9a7199efaf72c620b33f9767874f0ebced135d83
Groovy: 1.8.6
Ant: Apache Ant(TM) version 1.8.4 compiled on May 22 2012
Ivy: 2.2.0
JVM: 1.7.0_25 (Oracle Corporation 23.25-b01)
OS: Windows 8 6.2 amd64
Založenie projektu
Od verzie 1.7-rc-1 môžeme veľmi jednoducho založiť nový projekt. (Implementovala sa dlho požadovaná vlastnosť GRADLE-1289.)
V adresári s projektami založme podadresár s projektom:
mkdir spark-hello
a
cd spark-hello
Vytvorenie kostry projektu
Kostru projektu spustíme zavolaním tasku setupBuild
, ktorý nainicializuje adresárovú štruktúru a pripraví konfiguračné súbory.
Task v Gradle plní podobnú úlohu ako task v Ant-e, či goal v Mavene: realizuje nejakú komplexnú úlohu — existuje task na skompilovanie projektu, iný task na vybudovanie JARu a podobne.
Keďže chceme vytvárať bežný Java projekt, použijeme pre typ projektu hodnotu java-library
.
gradle setupBuild --type java-library
V tejto verzii Gradlu je zatiaľ k dispozícii len málo typov projektov, v budúcnosti sa dodajú ďalšie.
Uvidíme výsledok:
c:\Projects\spark-hello>gradle setupBuild --type java-library
:wrapper
:setupBuild
BUILD SUCCESSFUL
Total time: 2.563 secs
Tento task vytvorí zároveň adresárovú štruktúru s obslužnými súbormi:
c:\Projects\spark-hello>tree /F
Folder PATH listing
Volume serial number is 0051ECBC 5889:C1DD
C:.
│ build.gradle
│ gradlew
│ gradlew.bat
│ settings.gradle
│
├───.gradle
│ └───1.7-rc-1
│ └───taskArtifacts
│ cache.properties
│ cache.properties.lock
│ fileHashes.bin
│ fileSnapshots.bin
│ outputFileStates.bin
│ taskArtifacts.bin
│
├───gradle
│ └───wrapper
│ gradle-wrapper.jar
│ gradle-wrapper.properties
│
└───src
├───main
│ └───java
│ Library.java
│
└───test
└───java
LibraryTest.java
Adresárová štruktúra je podobná Mavenu:
- v
src/main/java
sú bežné Java zdrojáky, - v
src/test/java
sú zdrojáky unit testov.
Ako vidno, Gradle dodal ukážkový súbor Library.java
a prislúchajúci unit test.
V adresári projektu sa nachádzajú dva konfiguračné súbory:
build.gradle
je zostavovací skript (build skript), teda popisovač projektu, ktorý obsahuje všetko, čo je potrebné na zostavenie projektu. Je to analógiapom.xml
z Mavenu alebobuild.xml
z Antu.settings.gradle
obsahuje dodatočné špecifické nastavenia pre projekt.
Ostatné súbory (napr. gradle-wrapper.jar
) súvisia s tzv. Gradle Wrapperom, čo je spôsob, ako je možné spustiť Gradle bez toho, aby bolo v systéme nainštalované. Táto pokročilá vlastnosť nebude v tomto článku rozoberaná.
Zostavovací skript build.gradle
Súbor build.gradle
je najdôležitejší súbor pre gradleovský projekt: obsahuje temer všetky konfiguračné nastavenia pre zostavenie projektu.
Na rozdiel od Mavenu, ktorý sa zoširoka sa vyhýbal programovaniu v XML, je Gradle akýmsi návratom naspäť k Antu a jeho explicitným programom v XML. Zostavovací skript je skript, teda program, a to v jazyku Groovy. Silne stavia na syntaktických možnostiach tohto jazyka a umožňuje zápis, ktorý je často omnoho prehľadnejší než XML.
Gradle vygeneroval ukážkový skript:
/*
* This build file was auto generated by running the Gradle 'buildSetup' task
* by 'novotnyr' at '18.7.2013 12:14' with Gradle 1.7-rc-1
*
* This generated file contains a sample Java project to get you started.
* For more details take a look at the Java Quickstart chapter in the Gradle
* user guide available at http://gradle.org/docs/1.7-rc-1/userguide/tutorial_java_projects.html
*/
// Apply the java plugin to add support for Java
apply plugin: 'java'
// In this section you declare where to find the dependencies of your project
repositories {
// Use 'maven central' for resolving your dependencies.
// You can declare any Maven/Ivy/file repository here.
mavenCentral()
}
// In this section you declare the dependencies for your production and test code
dependencies {
// The production code uses the SLF4J logging API at compile time
compile 'org.slf4j:slf4j-api:1.7.5'
// Declare the dependency for your favourite test framework you want to use in your tests.
// TestNG is also supported by the Gradle Test task. Just change the
// testCompile dependency to testCompile 'org.testng:testng:6.8.1' and add
// 'test.useTestNG()' to your build script.
testCompile "junit:junit:4.11"
}
Polovicu skriptu zaberajú komentáre s klasickou C/Java syntaxou (buď dve lomky //
alebo /* ... */
. Po vyhodení komentárov sa skript zjednoduší na:
apply plugin: 'java'
repositories {
mavenCentral()
}
dependencies {
compile 'org.slf4j:slf4j-api:1.7.5'
testCompile "junit:junit:4.11"
}
Plug-iny
Prvý riadok zavedie do gradleovského projektu plug-in pre Java projekty. Plug-in obvykle sprístupní ďalšie tasky a zavedie konvencie pre umiestnenie zdrojových súborov: napr. tento plug-in pre Javu sprístupní tasky pre skompilovanie zdrojákov v src/main/java
a src/test/java
, pre generovanie dokumentácie JavaDoc, či pre vytvorenie JARu.
Závislosti
Preskočme na chvíľu blok repositories
a venujme sa závislosťam. V bloku dependencies
môže projekt uviesť závislosti, teda všetky ostatné projekty, či knižnice, na ktorých náš projekt závisí. Typický projekt funguje ako stavebnica z kociek iných projektov: napr. tento ukážkový projekt využíva na logovanie knižnicu slf4j.
Každá závislosť je jednoznačne identifikovaná trojicou:
* názvom skupiny: obvykle názov spoločnosti, či názov odvodený z webovej adresy projektu. Príkladom je org.slf4j
.
* názvom artefaktu: teda názvom samotného knižnice, či jej modulu: v tomto prípade závisíme na module, ktorý je identifikovaný ako org.slf4j
.
* a jeho verziou — napr. 1.7.5
Inými príkladom je závislosť na klasickej knižnici pre unit testy: závisíme na verzii 4.11.
Závislosti majú ešte tzv. scope, teda stav projektu, kde je závislosť vyžadovaná. Naše závislosti využívajú dva scopes:
- compile znamená, že závislosť je potrebná na to, aby sa projekt vôbec dal zostaviť.
- testCompile znamená, že závilosť je potrebná na zostavenie unit testov, ale samotný projekt sa dá zostaviť aj bez nej, ba dokonca bez nej aj pobeží.
Povedali sme, že máme dve závislosti. V reči Javy to znamená, že náš projekt potrebuje ku skompilovaniu získať ich JAR súbory. Odkiaľ ich však zoženieme?
Repozitáre
Z repozitára, ktorý si možno predstaviť ako analógiu správcu balíčkov z Linuxu alebo ako akýsi “obchod so všetkými JARkami všetkých možných projektov”, sa ťahajú projektové závislosti. Štandardný svetový repozitár pre JAR súbory je tzv. Maven Central s množstvom zrkadiel po celom svete.
Projekt môže deklarovať aj vlastné repozitáre: nejedna firma má svoj vlastný klon repozitára pre JARy vlastných projektov.
Repozitáre deklarujeme v sekcii repositories
:
repositories {
mavenCentral()
}
V našom projekte sme takto vyhlásili, že všetky závislosti budeme ťahať z webového mavenovského centrálneho úložiska.
Programovanie v Sparku
Poďme teraz urobiť skúšobný projekt v Sparku.
Dodanie závislosti
Dodajme do projektu závislosť na knižnici Spark. V dokumentácii tejto knižnice sa uvádza, že ak chceme pridať túto knižnicu do Mavenu, potrebujeme zaviesť závislosť:
<dependency>
<groupId>com.sparkjava</groupId>
<artifactId>spark-core</artifactId>
<version>1.0</version>
</dependency>
Keďže sme však v Gradli, potrebujeme ju uviesť v inom tvare. Závislosť bude uvedená v klasickom scope compile
a zložky oddelíme dvojbodkami.
dependencies {
compile 'com.sparkjava:spark-core:1.0'
compile 'org.slf4j:slf4j-api:1.7.5'
testCompile "junit:junit:4.11"
}
Vytvorenie demo triedy
Vykradnime ukážkový príklad z dokumentácie a vytvorme triedu HelloWorld
.
c:\Projects\spark-hello> notepad src/main/java/HelloWorld.java
Jej obsahom nech je:
import static spark.Spark.*;
import spark.*;
public class HelloWorld {
public static void main(String[] args) {
get(new Route("/hello") {
@Override
public Object handle(Request request, Response response) {
return "<h1>Hello World!</h1>";
}
});
}
}
Obdivovanie zoznamu taskov
Programovacia časť je za nami, poďme zostavovať. Zoznam dostupných taskov si môžeme pozrieť cez:
gradle tasks
Výsledkom bude zoznam taskov i s popisom: napr. assemble
zostaví (skompiluje) projekt, build
zostaví projekt a spustí unit testy a jar
vytvorí JAR archív.
Zostavenie projektu
Teraz už vieme, že projekt zostavíme cez:
gradle build
Gradle bude chvíľu chrústať a najmä sťahovať závislosti (a ich závislosti) z repozitára Maven Central.
:compileJava
Download http://repo1.maven.org/maven2/com/sparkjava/spark-core/1.0/spark-core-1.0.pom
Download http://repo1.maven.org/maven2/org/eclipse/jetty/jetty-server/9.0.2.v20130417/jetty-server-9.0.2.v20130417.pom
Download http://repo1.maven.org/maven2/org/eclipse/jetty/jetty-project/9.0.2.v20130417/jetty-project-9.0.2.v20130417.pom
Download http://repo1.maven.org/maven2/org/eclipse/jetty/jetty-webapp/9.0.2.v20130417/jetty-webapp-9.0.2.v20130417.pom
Download http://repo1.maven.org/maven2/org/eclipse/jetty/jetty-http/9.0.2.v20130417/jetty-http-9.0.2.v20130417.pom
Download http://repo1.maven.org/maven2/org/eclipse/jetty/jetty-io/9.0.2.v20130417/jetty-io-9.0.2.v20130417.pom
Download http://repo1.maven.org/maven2/org/eclipse/jetty/jetty-xml/9.0.2.v20130417/jetty-xml-9.0.2.v20130417.pom
Download http://repo1.maven.org/maven2/org/eclipse/jetty/jetty-servlet/9.0.2.v20130417/jetty-servlet-9.0.2.v20130417.pom
Download http://repo1.maven.org/maven2/org/eclipse/jetty/jetty-util/9.0.2.v20130417/jetty-util-9.0.2.v20130417.pom
Download http://repo1.maven.org/maven2/org/eclipse/jetty/jetty-security/9.0.2.v20130417/jetty-security-9.0.2.v20130417.pom
Download http://repo1.maven.org/maven2/com/sparkjava/spark-core/1.0/spark-core-1.0.jar
Download http://repo1.maven.org/maven2/org/eclipse/jetty/jetty-util/9.0.2.v20130417/jetty-util-9.0.2.v20130417.jar
Download http://repo1.maven.org/maven2/org/eclipse/jetty/jetty-http/9.0.2.v20130417/jetty-http-9.0.2.v20130417.jar
Download http://repo1.maven.org/maven2/org/eclipse/jetty/jetty-io/9.0.2.v20130417/jetty-io-9.0.2.v20130417.jar
Download http://repo1.maven.org/maven2/org/eclipse/jetty/jetty-server/9.0.2.v20130417/jetty-server-9.0.2.v20130417.jar
Download http://repo1.maven.org/maven2/org/eclipse/jetty/jetty-xml/9.0.2.v20130417/jetty-xml-9.0.2.v20130417.jar
Download http://repo1.maven.org/maven2/org/eclipse/jetty/jetty-security/9.0.2.v20130417/jetty-security-9.0.2.v20130417.jar
Download http://repo1.maven.org/maven2/org/eclipse/jetty/jetty-servlet/9.0.2.v20130417/jetty-servlet-9.0.2.v20130417.jar
Download http://repo1.maven.org/maven2/org/eclipse/jetty/jetty-webapp/9.0.2.v20130417/jetty-webapp-9.0.2.v20130417.jar
:processResources UP-TO-DATE
:classes
:jar
:assemble
:compileTestJava
:processTestResources UP-TO-DATE
:testClasses
:test
:check
:build
BUILD SUCCESSFUL
Total time: 10.934 secs
Task build
v skutočnosti zavolal viacero iných taskov. Z tých najdôležitejších: pomocou compileJava
skompiloval všetky javácke zdrojáky, potom vytvoril pomocou jar
výsledný JAR súbor, následne skompiloval unit testy cez compileTestJava
a spustil ich cez test
.
Výsledkom behu je, že v adresári build/libs
sa ocitne JAR s našim projektom:
c:\Projects\spark-hello\build\libs\spark-hello.jar
Bokom poznamenajme, že všetky závislosti stiahnuté z webu sa sťahujú do adresára .gradle
v domovskom adresári používateľa (napr. do C:/Users/novotnyr/.gradle
).
Prvý beh síce trval cca 10 sekúnd, ale väčšinu času zabralo sťahovanie závislosti, ktoré sa deje len raz. Druhý beh na ukážkovom stroji trval už len cca 3 sekundy.
Spustenie projektu
Ako spustíme projekt, ktorý má triedu s metódou main()
? Jedna možnosť je zhromaždiť všetky závislosti v jednom adresári, tiahlo nakonfigurovať CLASSPATH
, najlepšie v nejakom .bat
/.sh
súbore a následne ho spustiť.
V Gradli však môžeme použiť plug-in application
, ktorý nám prácu značne uľahčí.
Plug-in pre aplikácie
Dodajme na začiatok buildovacieho skriptu:
apply plugin:'application'
Na koniec skriptu dodajme deklaráciu, ktorou určíme hlavnú triedu s metódou main()
v projekte. Musíme uviesť celý názov triedy, vrátane balíčkov. Keďže naša trieda nie je v žiadnom balíčku, bude to jednoduché:
mainClassName = "HelloWorld"
Celý buildovací skript bude vyzerať:
apply plugin: 'java'
apply plugin: 'application'
repositories {
mavenCentral()
}
dependencies {
compile 'com.sparkjava:spark-core:1.0'
compile 'org.slf4j:slf4j-api:1.7.5'
testCompile "junit:junit:4.11"
}
Projekt spustíme cez:
gradle run
Uvidíme:
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:run
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details
== Spark has ignited ...
>> Listening on 0.0.0.0:4567
> Building > :run
Gradle ostal bežať, pretože sme spustili sparkovský HTTP server, ktorý čaká na naše požiadavky. Stačí navštíviť adresu vo webovom prehliadači a uvidime výsledok:
http://localhost:4567/hello
Server môžeme zastaviť bežným spôsobom: napr. stlačením Ctrl-C v konzole.
Vypustenie verzie
Upratanie nepotrebných súborov
Teraz, keď sme už skoro na konci, upraceme (teda vymažeme) demonštračné triedy Library.java
a LibraryTest.java
:
c:\Projects\spark-hello>del src\main\java\Library.java
c:\Projects\spark-hello>del src\test\java\LibraryTest.java
Nebudeme potrebovať ani závislosti pre *slf4j. Upravme teda blok dependencies
:
dependencies {
compile 'com.sparkjava:spark-core:1.0'
testCompile "junit:junit:4.11"
}
V skutočnosti sa môžeme zbaviť aj závislosti na JUnite, keďže nemáme žiadne unit testy.
Vytvorenie distribučného archívu
Gradle obsahuje v rámci plug-inu application
aj tasky, ktorými môžeme jednoducho vytvoriť ZIP súbor s aplikáciou a všetkými jej závislosťami. Táto funkcionalita je síce len v inkubačnej fáze (teda môže obsahovať viac chýb než je zvyklosťou, resp. spôsob použitia sa ešte môže neskôr meniť), ale pre jednoduché prípady funguje.
Spusťme teda:
gradle distZip
a výsledkom bude kompletný ZIP:
c:\Projects\spark-hello\build\distributions\spark-hello.zip
Ten obsahuje dokonca skripty pre Windows a Linux, ktorými aplikáciu môžeme ihneď po rozbalení spustiť.
Alternatívna možnosť je spustenie gradle distTar
, ktorou vznikne .tar.gz
podoba nášho projektu
Sumár
Ukázali sme si, ako možno jednoducho naštartovať projekt (gradle setupBuild
), ako ho zostaviť (gradle build
), ako ho spustiť pomocou plug-inu application
(gradle run
) a ako z neho vytvoriť distribučnú verziu (gradle distZip
).
Samozrejme, toto je len ľahké škrabnutie po povrchu mocného nástroja. Podrobnejšie info nájdete v hore zmienenom vychádzajúcom seriáli SoftWare Samuraja alebo priamo v dokumentácii.
Pěkný článek. Akorát se musím podívat, co je to ten Spark.
Spark je úplne jednoduchučký HTTP framework, ktorý stavia na priamočiarom API a na tom, že netreba žiadny servletový kontajner. Na testovanie zrejme výhodné.