danilo.pianini@unibo.itgianluca.aguzzi@unibo.itangelo.filaseta@unibo.itCompiled on: 2025-12-05 — versione stampabile
Questo materiale è ampiamente basato su quello realizzato dai Prof. Mirko Viroli e Roberto Casadei, che ringrazio.
Ogni errore riscontratovi è esclusiva responsabilità degli autori di questo documento.
La costruzione dei “deliverable” è parte integrante del processo di costruzione del software:
Gradle mappa con i task il processo di costruzione del software
L’esecuzione di un task implica l’esecuzione di tutti i precedenti!
jar (implica compileJava): costruisce un deliverable del progetto correnteassemble (implica jar): costruisce gli artefatti “deliverable”build: esegue sia check che assembleUn buon modo per eseguire l’intero ciclo di vita è ./gradlew build javadoc!
Finora, abbiamo visto che un’applicazione Java è composta di un insieme di classi: noi vorremmo distribuirla come singolo file!
Normalmente, le applicazioni Java vengono confezionate in file JAR (Java ARchive)
Un JAR è un archivio compresso con algoritmo ZIP che contiene le classi, le risorse (e.g. icone) e un file descrittivo detto Manifest.
Il Manifest viene creato sempre in META-INF/MANIFEST.MF, e
contiene informazioni sull’applicazione, ad esempio su quale classe
contenga il main del programma.
È possibile associare (a livello di sistema operativo) l’esecuzione del JAR file al comando Java, in modo che l’applicazione si avvii automaticamente “col doppio click” (avviando automaticamente la classe scritta nel Manifest)
È possibile utilizzare i file JAR come componenti di altre applicazioni (librerie)
jarPer creare un file JAR, si può utilizzare direttamente il comando jar
c — Specifica l’intenzione di creare un JAR filef — Specifica un file di output (se non presente, l’output è rediretto su
standard output)m — Specifica l’intenzione di allegare un manifest file personalizzato (se non
presente, ne viene creato uno di default, che non specifica alcuna classe da
eseguire)jar cf jar-file.jar file1 file2 directory1
jar-file.jar contenente file1,
file2, e directory1. Include un Manifest di default.jar cf jar-file.jar *
jar-file.jar contenente tutti i file
e le directory nel path corrente. Include un Manifest di default.jar cfm jar-file.jar MYMANIFEST it/unibo/*
jar-file.jar, contenente tutti i
file e le directory nel path it/unibo, con manifest dato dal file
MYMANIFEST nella cartella corrente.java ha un’opzione che consente l’esecuzione di file jar: -jar
Quando si lancia java -jar nomefile.jar,
la Java Virtual Machine automaticamente legge il file Manifest,
cerca una descrizione della Main Class da eseguire e tenta di eseguirla.
Il plugin java include un task chiamato jar che si occupa di creare un jar dell’applicazione corrente
*.class) e le risorse del source set main
src/mainPerché un Jar sia eseguibile, deve includere:
src/mainNoClassDefFoundError o delle ClassNotFoundException (in reflection)Un Jar file con queste caratteristiche viene definito anche fat-jar (o uber-jar, o shadow-jar)
Il plugin java non ha dei task preconfigurati per generare dei fat-jar.
Possiamo però sfruttare una coppia di altri plugin:
application: un plugin incluso in Gradle che configura una classe come “main class” per il software
run che compila il progetto e la eseguecom.gradleup.shadow: un plugin di terze parti
(ossia, costruito da una persona che non fa parte del team di Gradle)
shadowJar, che costruisce un jar con tutte le dipendenze specificate in Gradleapplication, cattura anche la main class e scrive il relativo fileNota: è sempre possibile costruire i propri task personalizzati, ma non è argomento di questo corso
application e com.gradleup.shadowplugins {
// Apply the java plugin to add support for Java
java
// Apply the application plugin to add support for building a CLI application
// You can run your app via task "run": ./gradlew run
application
/*
* Adds tasks to export a runnable jar.
* In order to create it, launch the "shadowJar" task.
* The runnable jar will be found in build/libs/projectname-all.jar
*/
id("com.gradleup.shadow") version "9.2.2"
id("org.danilopianini.gradle-java-qa") version "1.157.0"
}
application {
// Define the main class for the application.
mainClass.set("it.unibo.sampleapp.RateAMovie")
}
./gradlew run lancia your.mainclass.qualified.Name./gradlew shadowJar crea un fat-jar il cui nome termina in -all.jar dentro build/libsapplication con multipli main tramite proprietà di progettoNel caso in cui vi fossero più classi con un main, è possibile passare a Gradle il nome di classe da lanciare.
Per farlo, sfruttiamo il concetto di proprietà del progetto.
Le proprietà sono associazioni chiave-valore fra due stringhe che possono essere:
gradle.properties $\leftarrow$ per OOP cambia poco rispetto a scriverlo nel build.gradle.kts-Pnome=valore $\leftarrow$ utile se si hanno più mainScrivendo quanto segue nel build.gradle.kts
val myMainClass: String by project // prende la main class dalle proprietà di progetto
application {
mainClass.set(myMainClass)
}
È possibile poi scegliere la main class da avviare usando:
./gradlew run -PmyMainClass=...
... il nome qualificato della main class)Ad esempio, se abbiamo due classi con main it.unibo.oop.Pluto e it.unibo.oop.Paperino nel nostro progetto, possiamo lanciare:
./gradlew run -PmyMainClass=it.unibo.oop.Pluto
Pluto./gradlew run -PmyMainClass=it.unibo.oop.Paperino
Paperinodanilo.pianini@unibo.itgianluca.aguzzi@unibo.itangelo.filaseta@unibo.itCompiled on: 2025-12-05 — versione stampabile
Questo materiale è ampiamente basato su quello realizzato dai Prof. Mirko Viroli e Roberto Casadei, che ringrazio.
Ogni errore riscontratovi è esclusiva responsabilità degli autori di questo documento.