Il Maven 2 POM demistificato

Costruire un progetto è un'attività complessa. A causa delle dozzine di attività richieste per convertire il tuo miscuglio di file in un programma funzionante, esistono letteralmente centinaia di strumenti che fanno di tutto, dalla generazione del codice sorgente, alla compilazione, al test, alla distribuzione, alla preparazione del caffè mattutino (se ne trovi uno, caro lettore, fammelo sapere). Molti di questi programmi sono eccellenti in quello che fanno. Sfortunatamente, per quelli di noi che gestiscono sistemi di costruzione su larga scala per vivere, raramente ci sono molte cose in comune; ogni programma richiede la propria installazione e configurazione esoterica. È diventato un fatto inevitabile della nostra vita che la maggior parte dei sistemi di build sono costruiti su misura incollando a mano questi strumenti con diversi script homebrew (sì, contano gli script Ant).

Più di un altro strumento di compilazione, Maven è un framework di compilazione . Separa in modo pulito il codice dai file di configurazione, dalla documentazione e dalle dipendenze. Maven è sorprendentemente flessibile nel consentire agli utenti di configurare la maggior parte degli aspetti del proprio codice, nonché nel controllare il comportamento dei plug-in, gli obiettivi individuali e persino il ciclo di vita stesso della build. Maven è la struttura reale e, tra queste mura, il tuo progetto abita; vuole essere un ospite accomodante.

Ma il problema rimane ancora: gestire il lavoro di migliaia di script di build personalizzati all'interno di un unico framework è difficile e, per essere eseguito correttamente, richiede molte informazioni. Fortunatamente, il team di Maven 2 ha avuto un discreto successo. Imparando dagli errori di Maven 1, innumerevoli richieste degli utenti, modifiche e aggiornamenti, Maven 2 è più potente che mai. Sfortunatamente, con una grande potenza arriva una grande configurazione. Affinché gli artefatti di Maven 2 siano unità facilmente trasportabili, quella configurazione complessa cade in un unico file. Inserisci il Maven POM.

Cos'è il POM?

POM è l'acronimo di Project Object Model. È una rappresentazione XML di un progetto Maven contenuto in un file chiamato pom.xml. In presenza di Maven, parlare di un progetto è parlare in senso filosofico, al di là di una semplice raccolta di file contenenti codice. Un progetto contiene i file di configurazione, gli sviluppatori coinvolti e i ruoli che giocano, il sistema di tracciamento dei difetti, l'organizzazione e le licenze, l'URL in cui risiede il progetto, le dipendenze del progetto e tutti gli altri piccoli pezzi che entrano in gioco per fornire il codice vita. Un progetto è uno sportello unico per tutte le cose ad esso correlate. Infatti, nel mondo Maven, un progetto non ha bisogno di contenere alcun codice, solo un pom.xml. Incontreremo un paio di questi tipi di progetti più avanti nell'articolo.

Una rapida panoramica strutturale

Il POM è grande e complesso, quindi romperlo in pezzi facilita la digestione. Ai fini di questa discussione, questi pezzi sono raggruppati in quattro unità logiche, come mostrato nella Figura 1: relazioni POM, informazioni sul progetto, impostazioni di compilazione e ambiente di compilazione. Inizieremo discutendo delle relazioni POM.

Di seguito è riportato un elenco degli elementi direttamente sotto l'elemento del progetto del POM. Notare che modelVersioncontiene 4.0.0. Questa è attualmente l'unica versione POM supportata per Maven 2 ed è sempre richiesta. La definizione dello schema XML di Maven 4.0.0 si trova in //maven.apache.org/maven-v4_0_0.xsd. I suoi elementi di primo livello sono i seguenti:

4.0.0

... ... ... ... ... ... ...

... ... ... ... ... ... ... ...

... ... ... ...

... ... ... ...

... ... ... ... ...

Relazioni POM

Il nostro primo ordine del giorno è esaminare le relazioni del progetto, rappresentate nella Figura 2 come l'angolo in alto a sinistra del grafico nella Figura 1.

I progetti devono essere in qualche modo relazionati tra loro. Dalla creazione dei primi assemblatori, i progetti software hanno avuto dipendenze; Maven ha introdotto più forme di relazioni finora inutilizzate in tale forma per i progetti Java. Queste relazioni sono coordinate Maven, dipendenze basate su coordinate, ereditarietà del progetto e aggregazione.

Coordinate

Ogni progetto Maven contiene il proprio identificatore univoco, soprannominato le coordinate del progetto , che agisce come l'indirizzo di un artefatto, dandogli un posto unico nell'universo di Maven. Se i progetti non avessero modo di relazionarsi tra loro, le coordinate non sarebbero necessarie. Cioè, se un universo avesse solo una casa, perché avrebbe bisogno di un indirizzo come 315 Cherrywood Lane?

Il seguente codice è il POM minimo Maven 2 sarà allow- , e sono tutti campi. Agiscono come un vettore nello spazio Maven con gli elementi raggruppatore, identificatore e timestamp.

4.0.0org.codehaus.mojoa1

Nel mondo Maven, questi tre elementi principali (La trinità di Maven - guarda la sua gloria!) Costituiscono le coordinate di un POM. Le coordinate sono rappresentate dalla Figura 3.

Forse questo POM non è così impressionante di per sé. Va meglio.

Dipendenze

Uno degli aspetti più potenti di Maven è la sua gestione delle dipendenze del progetto, e in Maven 2, che include le dipendenze transitive. La figura 4 illustra come rappresentarli graficamente.

La gestione delle dipendenze ha una lunga tradizione di essere un pasticcio complicato per qualsiasi cosa tranne il più banale dei progetti. "Jarmageddon" segue rapidamente quando l'albero delle dipendenze diventa enorme, complicato e imbarazzante per gli architetti che sono disprezzati dai neolaureati che "avrebbero potuto farlo meglio". Segue "Jar Hell", dove le versioni delle dipendenze su un sistema non sono esattamente le stesse versioni di quelle usate per lo sviluppo; hanno la versione sbagliata o versioni in conflitto tra JAR con nomi simili. Quindi, le cose iniziano a rompersi e individuare il motivo per cui si rivela difficile. Maven risolve entrambi questi problemi avendo un repository locale comune da cui collegarsi ai progetti, alle versioni e tutto il resto corretti.

Eredità

Una delle caratteristiche che Maven 2 porta dai giorni Maven 1 è l'ereditarietà del progetto, come rappresentato nella Figura 5. Nei sistemi di compilazione, come Ant, l'ereditarietà può certamente essere simulata, ma Maven ha fatto il passo in più per rendere esplicita l'ereditarietà del progetto il modello a oggetti del progetto.

Il codice seguente definisce un POM padre in Maven 2:

4.0.0org.codehaus.mojob2pom

Questo genitore sembra simile al nostro primo POM, con una piccola differenza. Si noti che abbiamo impostato il packagingtipo su pom, che è richiesto sia per i progetti padre che per quelli aggregatori (tratteremo di più packagingnella sezione "Impostazioni di compilazione"). Se vogliamo utilizzare il progetto sopra come genitore, possiamo modificare il org.codehaus.mojo:aPOM del progetto in modo che sia:

4.0.0org.codehaus.mojob2a

It is important to note that all POMs inherit from a parent whether explicitly defined or not. This base POM is known as the "super POM," and contains values inherited by default. An easy way to look at the default configurations of the super POM is by creating a simple pom.xml with nothing but modelVersion, groupId, artifactId, and version, and running the command mvn help:effective-pom.

Beyond simply setting values to inherit, parents also have the power to create default configurations for their children without actually imposing values upon them. Dependency management is an especially powerful instrument for configuring a set of dependencies through a common location (a POM's parent). The dependencyManagement element syntax is similar to that of the dependency section. What it does, however, is allow children to inherit dependency settings, but not the dependency itself. Adding a dependency with the dependencyManagement element does not actually add the dependency to the POM, nor does it add a dependency to the children; it creates a default configuration for any dependency that a child may choose to add within its own dependency section. Settings by dependencyManagement also apply to the current POM's dependency configuration (although configurations overridden inside the dependency element always take precedence).

Aggregation

A project with modules is known as a multimodule project. Modules are projects that a POM lists, executed as a set. Multimodule projects know of their modules, but the reverse is not necessarily true, as represented in Figure 6.

Assuming that the parent POM resides in the parent directory of where POM for project a lives, and that the project a also resides in a directory of the same name, we may alter the parent POM b to aggregate the child a by adding it as a module:

4.0.0org.codehaus.mojob2poma

Now if we ran mvn compile in the base directory, you would see the build start with:

[INFO] Scanning for projects... [INFO] Reactor build order: [INFO] Unnamed – org.codehaus.mojo:b:pom:2 [INFO] Unnamed – org.codehaus.mojo:a:jar:2 

The Maven lifecycle will now execute up to the lifecycle phase specified in correct order; that is, each artifact is built one at a time, and if one artifact requires another to be built first, it will be.

A note on inheritance vs. aggregation

Inheritance and aggregation create a nice dynamic for controlling builds through a single, high-level POM. You will often see projects that are both parents and multimodules, such as the example above. Their complementariness makes them a natural match. Even the Maven 2 project core runs through a single parent/multimodule POM org.apache.maven:maven, so building a Maven 2 project can be executed by a single command: mvn compile. Although used in conjunction, however, a multimodule and a parent are not one in the same, and should not be confused. A POM project (acting as a parent) may be inherited from, but that parent project does not necessarily aggregate any modules. Conversely, a POM project may aggregate projects that do not inherit from it.

Quando tutti e quattro i pezzi dell'equazione sono stati messi insieme, si spera che vedrai la potenza del meccanismo di relazione di Maven 2, come mostrato nella Figura 7.

Maven ci fornisce una bella struttura per mettere in relazione i progetti tra loro e, attraverso queste relazioni, possiamo creare plug-in riutilizzabili da qualsiasi progetto seguendo le convenzioni di Maven. Ma la capacità di gestire le relazioni di progetto è solo una parte dell'equazione complessiva di Maven. Il resto del POM non si occupa di altri progetti, ma delle sue impostazioni di compilazione, delle sue informazioni e del suo ambiente. Con una rapida comprensione di come i progetti si relazionano tra loro, iniziamo a vedere come un POM contiene informazioni sul progetto vero e proprio.