Il build automation tool più famoso.
Maven è un software che permette di automatizzare il processo di build di un progetto basato su Java.
Nato sotto l'egida dell'Apache Software Foundation, ha come obiettivo quello di semplificare la gestione dello sviluppo software.
Abbiamo visto che, non appena un progetto software inizia ad includere più file o persino delle dipendenze esterne, il processo di compilazione inizia a diventare sempre più complesso.
Questo senza nemmeno considerare fattori come il testing, la distribuzione degli artefatti, la gestione delle versioni, la documentazione, la manipolazione del bytecode e così via.
Affinché il processo di build sia sempre riproducibile, bisogna quindi definire una sequenza di step standardizzata.
Anche in questo caso, poter definire tutti i dettagli in un file con un formato noto è praticamente una necessità.
Per poter utilizzare Maven, è necessario scaricandolo dal sito ufficiale ed installarlo o utilizzare il proprio gestore di pacchetti preferito.
Per assicurarci che l'installazione sia avvenuta con successo, si può controllare l'output del comando
mvn --version
Un help tooltip è disponibile con il comando
mvn -h
Per iniziare un nuovo progetto, è sufficiente creare una cartella e lanciare il comando
mvn archetype:generate \
-DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4
Il programma chiederà di inserire ulteriori informazioni:
Una volta creato il progetto, la struttura della cartella sarà la seguente:
.
├── pom.xml # file di configurazione per Maven
└── src
├── main
│ ├── java
│ │ └── edu
│ │ └── tend
│ │ └── App.java # codice sorgente
│ └── resources
└── test
├── java
│ └── edu
│ └── tend
│ └── AppTest.java # test
└── resources
Il file pom.xml
è un file xml che serve a configurare il comportamento di Maven.
Vi sono un numero spropositato di possibili configurazione utilizzabili.
Quelle necessarie, però, sono solo:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>edu.tend</groupId>
<artifactId>maven-1</artifactId>
<version>1</version>
</project>
Per estendere esplicitamente un pom, magari da un sotto-modulo, si può utilizzare il tag <parent>
:
<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>edu.tend</groupId>
<artifactId>maven-1</artifactId>
<version>1</version>
<!-- <relativePath>../original/pom.xml</relativePath> -->
</parent>
<artifactId>maven-module</artifactId>
</project>
La combinazione di groupId
, artifactId
e version
prende il nome di coordinate.
Tutti i progetti derivano implicitamente da un pom di default.
Per definire delle variabili, si può utilizzare il tag <properties>
.
<project>
<!-- ... -->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<la.mia.variabile>valore</la.mia.variabile>
</properties>
</project>
Alcune variabili speciali sono già definite, come ad esempio
Le variabili possono essere referenziate con la sintassi ${nome.variabile}
.
<project>
<!-- ... -->
<properties>
<mavenVersion>3.6.3</mavenVersion>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-artifact</artifactId>
<version>${mavenVersion}</version>
</dependency>
</dependencies>
</project>
Alcune variabili con nomi specifici potrebbero essere utilizzate implicitamente da plugin o da altri elementi del pom.
Uno degli aspetti più comodi di Maven è la gestione automatica delle dipendenze del progetto.
Per indicare una o più dipendenze, si può utilizzare il tag <dependencies>
.
<project>
<!-- ... -->
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-artifact</artifactId>
<version>${mavenVersion}</version>
</dependency>
</dependencies>
</project>
Lo scope indica il contesto in cui la dipendenza è utilizzata, se e quando deve essere inclusa e in quali fasi di build del progetto.
I possibili valori sono:
Per indicare la versione di una dipendenza, si utilizza il tag <version>
.
Si può anche specificare un range accettabile di versioni, dove []
indica inclusione e ()
esclusione.
<project>
<!-- ... -->
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>[3.0,4.11)</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Maven gestisce le dipendenze in maniera transitiva.
Se B
dipende da C
e D
, nel momento in cui A
utilizza B
, Maven si occuperà di aggiungere implicitamente le dipendenze di B
.
Loading diagram...
Se si vuole dare maggiore libertà di scelta sulla specifica dipendenza all'utente finale, è possibile aggiungere nella dipendenza il tag <optional>true</optional>
.
Maven organizza gli step di build in una serie di fasi, la cui sequenza prende il nome di lifecycle.
I tre lifecycle principali sono:
validate
, compile
, test
, package
, verify
, install
e deploy
.clean
, che rimuove tutti i file generati dalla build.site
, che genera il sito di documentazione del progetto.Come un lifecycle è una sequenza di fasi, una fase è una sequenza di goal.
Quando viene invocata una fase, Maven esegue tutte le fasi precedenti nel lifecycle, e per ciascuna fase esegue i goal corrispondenti.
Un goal è un task specifico che viene eseguito da Maven quando si arriva alla fase corrispondente, ma possono anche essere lanciati singolarmente.
I goal sono definiti dai plugin e ne prendono il nome:
maven-compiler-plugin:compile
maven-surefire-plugin:test
Loading diagram...
Un plugin forniscono un insieme di goal che per Maven.
Per aggiungere un plugin al progetto, si utilizza il tag <plugin>
.
<project>
<!-- ... -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
</configuration>
</plugin>
</plugins>
</build>
</project>
Maven permette di specificare una repository remota dove caricare il progetto per essere distribuito.
<project>
<!-- ... -->
<distributionManagement>
<repository>
<id>github</id>
<name>GitHub Packages</name>
<url>https://maven.pkg.github.com/User/Project</url>
</repository>
</distributionManagement>
</project>
Il repository remoto richiederà delle credenziali per potervi accedere.
Queste vanno specificate nel file ~/.m2/settings.xml
.