Cas pratiques

Installer Maven dans un pack, avec un JDK en dépendance

Un pack Maven qui dépend d'un pack JDK — versions choisies pour les deux, actions prédéfinies plutôt que du shell, et repo .m2 partagé avec le host.

Ce tutoriel construit deux packs : jdk, qui installe un OpenJDK dans une version choisie, et maven, qui en dépend et expose la commande mvn. Contrairement au tutoriel Pack Node.js, qui réduisait provision à un unique script shell, on utilise ici des actions typées — pkg, url, systempath, env — chaque fois que c’est possible.

Pourquoi deux packs, et pourquoi des actions plutôt que du shell ?

Maven a besoin d’un JDK pour fonctionner, mais ce JDK n’est pas un détail d’implémentation propre à Maven : d’autres packs (un serveur d’applications, un autre outil de build) en ont tout autant besoin, avec potentiellement une version différente. Un pack jdk autonome, dont maven déclare la dépendance, évite de dupliquer cette logique — et permet de choisir la version du JDK indépendamment de celle de Maven.

Une action typée comme pkg (installation de paquets) ou url (téléchargement mis en cache) porte une intention explicite, contrairement à une ligne de shell : pkg s’appuie sur le bon gestionnaire de paquets du système sous-jacent (apt, yum, …) sans que le pack ait à s’en soucier, et url ne retélécharge pas une ressource déjà présente dans le cache xbee (~/.xbee/cache-artefacts par défaut) — voir Actions.

Créer le pack jdk

mkdir maven-toolchain
cd maven-toolchain
xbee new pack jdk
cd jdk

Écrire le xbee-pack.yaml du pack jdk

schema-version: "1.0"
description: "OpenJDK, dans une version choisie."

require: ubuntu:24.04

var:
  xbee:
    version: "21"

provision:
  - pkg:
      name: "openjdk-{{ .xbee.version }}-jdk"
  - env: "JAVA_HOME=/usr/lib/jvm/java-{{ .xbee.version }}-openjdk-amd64"

command:
  java: java
  javac: javac
  • var.xbee.version surcharge la variable réservée xbee.version — la convention suivie par la plupart des packs xbee pour exposer la version d’un outil, plutôt qu’une clé var arbitraire : elle intervient dans l’identité du pack (nom, hash d’image) construite par xbee — voir Modèle de données.
  • pkg installe des paquets système via le gestionnaire du système sous-jacent — ici openjdk-21-jdk par défaut. Le paquet Debian/Ubuntu range le JDK dans /usr/lib/jvm/java-{{ .xbee.version }}-openjdk-amd64 et enregistre déjà java et javac dans le PATH via update-alternatives : pas besoin d’un systempath ici, contrairement au pack maven plus bas.
  • env expose une variable d’environnement dans le container — ici JAVA_HOME, au format NOM=valeur (raccourci équivalent à {name: JAVA_HOME, value: ...}).
  • command.java et command.javac exposent deux commandes de pack, pour tester le JDK isolément une fois installé.

Provisionner

xbee pack

provision system prépare ubuntu:24.04, puis provision installe le JDK déclaré — voir Packs.

Créer le pack maven, dépendant de jdk

À côté de jdk/ (pas dedans) :

cd ..
xbee new pack maven
cd maven

Écrire le xbee-pack.yaml du pack maven

schema-version: "1.0"
description: "Maven, dans une version choisie, avec un JDK en dépendance et le repo local .m2 partagé avec le host."

require: ubuntu:24.04

dependency:
  origin: ../jdk
  alias: jdk

var:
  xbee:
    version: "3.9.9"

provision:
  - url: https://archive.apache.org/dist/maven/maven-3/{{ .xbee.version }}/binaries/apache-maven-{{ .xbee.version }}-bin.tar.gz
  - systempath: "/opt/apache-maven-{{ .xbee.version }}/bin"

bind:
  repo:
    from: $HOME/.m2
    to: /home/{{ .xbee.user }}/.m2

command:
  mvn: mvn
  • dependency.origin référence le pack jdk de ce tutoriel, avec la même syntaxe
    relative que le pack d’un hôte d’environnement. alias: jdk nomme cette dépendance
    c’est ce nom qui permettra de surcharger la version du JDK depuis l’extérieur, sans toucher ni à maven ni à jdk — voir plus bas.
  • var.xbee.version est la version de Maven — même convention que dans le pack jdk, indépendante de celle du JDK.
  • url, réduit à une chaîne, télécharge l’archive (mise en cache dans ~/.xbee/cache-artefacts) et la dépaquette — par défaut dans {{ .xbee.install }} (/xbee/install), avec unpack: true — voir Actions. L’archive Maven dépaquette un répertoire apache-maven-{{ .xbee.version }}/ directement sous /opt, d’où le chemin du systempath qui suit.
  • systempath, réduit à une chaîne, ajoute ce répertoire bin au PATH du container — ici nécessaire, à la différence du JDK, puisque l’archive Maven n’enregistre rien elle-même via update-alternatives.
  • bind.repo monte le répertoire .m2 du host ($HOME/.m2 — la variable d’environnement est résolue côté host, pas dans le container) sur celui de l’utilisateur du pack côté guest (.xbee.user, default sauf surcharge). Contrairement à un -v de commande de pack, ce montage est automatique à chaque démarrage de container pour ce pack — au provisioning, mais aussi à chaque invocation de mvn — de sorte que le cache de dépendances Maven survit d’un appel à l’autre sans jamais être reconstruit depuis zéro.
  • command.mvn expose la commande xbee mvn.

Provisionner

xbee pack

Une dépendance est installée dans l’image du pack avant l’installation du pack lui-même — voir Packs. xbee installe donc d’abord jdk dans l’image, puis y ajoute Maven par-dessus.

Exposer la commande depuis un projet

Comme pour le pack nodejs du tutoriel précédent, mvn n’est pas invocable tant que maven n’est pas installé — voir Exposer les commandes du pack. Depuis un projet Maven existant (ou un nouveau répertoire pour un essai), un xbee-install.yaml :

schema-version: "1.0"

pack: ../maven

expose mvn dans ce répertoire, avec le répertoire courant monté sur /xbee/app :

xbee mvn --version

affiche la version de Maven et celle du JDK sous-jacent — la preuve que la dépendance a bien été résolue et provisionnée dans la même image.

Vérifier le partage du repo .m2

xbee mvn -f /xbee/app/pom.xml dependency:resolve

sur un projet avec un pom.xml, télécharge les dépendances Maven dans /home/default/.m2 côté guest — c’est-à-dire, grâce au bind, dans $HOME/.m2 sur le host. Un second appel, ou un appel depuis un tout autre projet utilisant ce même pack maven, réutilise ce cache sans retélécharger quoi que ce soit.

Surcharger les versions

La version de Maven se surcharge comme toute valeur var, en la ciblant directement :

pack:
  origin: ../maven
  var:
    xbee:
      version: "3.8.8"

La version du JDK, elle, appartient au modèle de la dépendance : elle se surcharge par le nom de son alias, en notation à points — exactement comme dans l’exemple de xbee-pack.yaml :

pack:
  origin: ../maven
  var:
    jdk.xbee.version: "17"

Ce second exemple ne touche ni à maven/xbee-pack.yaml ni à jdk/xbee-pack.yaml : la résolution de dépendance associe jdk. au pack aliasé jdk, et n’en retient que la partie xbee.version.

Pour aller plus loin

  • Le détail complet des actions typées (copy, github, permission, Folder, …) au-delà de pkg, url, systempath et env — voir Actions.
  • up/down pour un pack qui, contrairement à maven, démarre un vrai service — voir le pack hello du tutoriel Pack minimal.
  • Toutes les propriétés reconnues dans un xbee-pack.yaml, dont dependency et bind — voir xbee-pack.yaml.
  • Référencer plusieurs packs (jdk et maven) dans un même xbee-install.yaml, pour exposer java/javac en plus de mvn — non couvert par ce tutoriel.