Esempio di gestione dipendenze di un progetto Maven

Prerequisiti

Per seguire il tutorial “Esempio di gestione dipendenze di un progetto Maven” è necessario

  • ll Tool Apache Maven deve essere già installato sul PC. Se non l’hai ancora fatto ti consiglio l’articolo su come Installare Maven su Windows 10.
  • Sapere cos’è una fase Maven e dove si colloca all’interno di un ciclo di vita di Build. Se vuoi approfondire questo punto vai al Tutorial Maven per Principianti.
  • Conoscere la funzione che ricopre un file pom.xml all’interno di un progetto Maven.

Creazione del progetto Maven

Per i nostri scopi non sono necessari IDE quali Eclipse o IntelliJ, sarà invece sufficiente affidarsi al tool di build Maven.
Generiamo quindi un progetto Maven minimale, digitando la seguente istruzione dal prompt dei comandi, a partire dalla cartella C:\

C:\>mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-simple -DarchetypeVersion=1.4

e premiamo Invio

Inizialmente Maven produrrà un output simile a quello in figura

Esempio di gestione delle dipendenze Maven

Dopo alcuni secondi di attesa dovuti all’elaborazione, ci verranno chiesti alcuni dettagli inerenti al progetto che stiamo andando a creare: digitiamo da riga di comando i valori che vogliamo assegnare ai parametri richiesti e diamo ogni volta Invio per proseguire.

Per groupId assegniamo il valore org.marcoparoni . È il nome del gruppo di lavoro di appartenenza (in generale il dominio dell’azienda, ma nel nostro caso va bene qualsiasi cosa in quanto utenti singoli)
Per artifactId assegniamo il valore MvnProject . È il nome del progetto e quindi anche il nome della cartella principale che verrà generata all’interno di C:\
Per version inseriamo 1.0 siccome il progetto sta venendo creato per la prima volta. Essa infatti rappresenta la versione.
Per package e le successive richieste di inserimento dati premiamo sempre Invio senza inserire nulla.
Se alla fine otteniamo “BUILD SUCCESS” dal prompt dei comandi significa che la creazione del progetto è andata a buon fine. Vedremo quindi comparire la cartella “MvnProject” direttamente in C:\

Esempio di gestione delle dipendenze Maven

Aggiungiamo le dipendenze

Il pom.xml che troveremo già pronto nella root del progetto “MvnProject” sarà simile al seguente

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>org.marcoparoni</groupId>
	<artifactId>MvnProject</artifactId>
	<version>1.0</version>

	<name>MvnProject</name>
	<description>A simple MvnProject.</description>
	<!-- FIXME change it to the project's website -->
	<url>http://www.example.com</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<maven.compiler.source>1.7</maven.compiler.source>
		<maven.compiler.target>1.7</maven.compiler.target>
	</properties>

	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
		</dependency>
	</dependencies>

	<build>
		<pluginManagement>
			<!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
			<plugins>
				<plugin>
					<artifactId>maven-clean-plugin</artifactId>
					<version>3.1.0</version>
				</plugin>
				<plugin>
					<artifactId>maven-site-plugin</artifactId>
					<version>3.7.1</version>
				</plugin>
				<plugin>
					<artifactId>maven-project-info-reports-plugin</artifactId>
					<version>3.0.0</version>
				</plugin>
				<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
				<plugin>
					<artifactId>maven-resources-plugin</artifactId>
					<version>3.0.2</version>
				</plugin>
				<plugin>
					<artifactId>maven-compiler-plugin</artifactId>
					<version>3.8.0</version>
				</plugin>
				<plugin>
					<artifactId>maven-surefire-plugin</artifactId>
					<version>2.22.1</version>
				</plugin>
				<plugin>
					<artifactId>maven-jar-plugin</artifactId>
					<version>3.0.2</version>
				</plugin>
				<plugin>
					<artifactId>maven-install-plugin</artifactId>
					<version>2.5.2</version>
				</plugin>
				<plugin>
					<artifactId>maven-deploy-plugin</artifactId>
					<version>2.8.2</version>
				</plugin>
			</plugins>
		</pluginManagement>
	</build>

	<reporting>
		<plugins>
			<plugin>
				<artifactId>maven-project-info-reports-plugin</artifactId>
			</plugin>
		</plugins>
	</reporting>
</project>

Per aggiungere una nuova dipendenza è sufficiente inserire il seguente codice XML, subito dopo l’elemento <dependencies> (riga 22 del pom.xml)

<dependency>
	<groupId>commons-logging</groupId>
	<artifactId>commons-logging</artifactId>
	<version>1.1.1</version>
</dependency>

Tale dipendenza fornisce al nostro progetto Java la possibilità di usare i messaggi di log della libreria Apache Commons Logging. Vediamo ora come mostrarli durante l’esecuzione del programma.

Alla creazione del progetto, tra le altre cose, è stata creata anche una classe App.java, che troviamo a partire dalla root principale MvnProject sotto il percorso src\main\java\org\marcoparoni.
Modifichiamola come riportato qui sotto per poter utilizzare i sopracitati messaggi di log.

package org.marcoparoni;

/**
 * Hello world!
 *
 */
 
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
 
public class App 
{
	
	private static Log log = LogFactory.getLog(App.class);
	
    public static void main( String[] args )
    {
        //System.out.println( "Hello World!" );
		log.info("livello info nel metodo main");
    }
}

In riferimento al codice, teniamo a mente per i passaggi a venire che la classe LogFactory contenuta all’interno della dipendenza commons-logging è quella che effettivamente fornisce i messaggi di log.

Compilazione del codice sorgente e packaging

Torniamo a Maven per la compilazione del codice e per il packaging del progetto. Apriamo quindi il prompt dei comandi dalla root “MvnProject” e digitiamo:

C:\MvnProject>mvn package

ottenendo come output

Esempio di gestione delle dipendenze Maven

Siccome non è mai stata usata prima, notiamo che la dipendenza commons-logging viene scaricata dal Maven Repository e depositata nella cache locale /.m2 (per saperne di più vai alla pagina Gestione delle dipendenze Maven, che ti fornirà le basi teoriche per affrontare meglio questo tutorial).
Successivamente, durante la fase di compile, il plugin associato crea in automatico un classpath contenente il percorso locale delle dipendenze indicate nel pom.xml.
Nel nostro caso quindi avremo un classpath così descritto:

[DEBUG]   (f) compilePath = [C:\MvnProject\target\classes, C:\Users\NomeUtente\.m2\repository\commons-logging\commons-logging\1.1.1\commons-logging-1.1.1.jar, C:\Users\NomeUtente\.m2\repository\junit\junit\3.8.1\junit-3.8.1.jar]

Abbiamo così evidenziato come la dipendenza commons-logging appena scaricata, venga utilizzata per la costruzione del classpath necessario alla fase di compilazione. Ecco una rappresentazione grafica di ciò che accade:

Infine la fase di package crea il programma eseguibile “MvnProject-1.0.jar” all’interno della cartella /target.

Eseguire il programma

L’ ultimo passo da compiere è l’esecuzione del nostro programma! Dal prompt dei comandi spostiamoci quindi in C:\MvnProject\target e digitiamo l’istruzione seguente

C:\MvnProject\target>java -jar MvnProject-1.0.jar

Cosa succede? Il programma non parte e compare il messaggio di errore:

Esempio di gestione delle dipendenze Maven

Questo avviene perchè all’interno dell’eseguibile “MvnProject-1.0.jar” va indicato (qual’ora non sia già stato fatto da Maven, ma non è questo il caso) il nome della classe contenente il metodo main().

Decomprimiamo quindi “MvnProject-1.0.jar” con un programma quale WinRar o 7-Zip e rechiamoci nella cartella META-INF

All’interno di META-INF troveremo il file MANIFEST-MF da modificare. Apriamolo con un editor di testo quale Notepad ++ e inseriamo la seguente riga in cima alle altre già presenti:

Main-Class: org.marcoparoni.App

Non vanno lasciati spazi come evidenziato nell’immagine:

Chiudiamo l’archivio, salviamo e proviamo ora a rieseguire il programma…..ci da ancora errore!
Questa volta è differente, viene infatti mostrata un’ eccezione java.lang.NoClassDefFoundError:

Cosa significa questo errore? In sostanza ci viene detto che il programma non riesce a trovare la classe LogFactory appartenente alla dipendenza commons-logging. Ciò significa che in questo caso Maven si è occupato di gestire la dipendenza solamente per la fase di compilazione, passando al compilatore il classpath che mostrato in precedenza.

Risulta quindi evidente come in fase di run-time la dipendenza non venga gestita da Maven.
Per indicare a Maven di inserire la dipendenza commons-logging all’interno dell’eseguibile, inseriamo lo snippet riportato sotto all’interno del pom.xml, subito dopo il tag <build>

	<plugins>
			<plugin>
				<artifactId>maven-assembly-plugin</artifactId>
				<executions>
					<execution>
						<phase>package</phase>
						<goals>
							<goal>single</goal>
						</goals>
					</execution>
				</executions>
				<configuration>
					<descriptorRefs>
						<descriptorRef>jar-with-dependencies</descriptorRef>
					</descriptorRefs>
				</configuration>
			</plugin>
	</plugins>

Rieseguiamo le fasi di compilazione e packaging, premurandoci questa volta di “ripulire” la cartella \target digitando anche il buildlifecycle clean:

C:\MvnProject>mvn clean package

Al termine dell’esecuzione otterremo due versioni dell’eseguibile:
1)”MvnProject-1.0.jar” che è la stessa di prima
2) Stavolta anche “MvnProject-1.0-jar-with-dependencies.jar” che è quella contenente la dipendenza

Modificando il file MANIFEST-MF anche per MvnProject-1.0-jar-with-dependencies.jar, come già mostrato ad inizio paragrafo per MvnProject-1.0.jar, possiamo ora eseguire il programma:

C:\MvnProject\target>java -jar MvnProject-1.0-jar-with-dependencies.jar

Missione compiuta! Adesso il programma mostra correttamente da linea di comando il messaggio di log inserito nella classe App.java

Complimenti, hai terminato con successo il tutorial Esempio di gestione dipendenze di un progetto Maven! Qua sotto sono riportati alcuni riferimenti esterni utili

Riferimenti esterni

maven.apache.org

Precedente Gestione delle dipendenze Maven Successivo Installare Maven su Windows 10