Aller au contenu
English
Compte : non connecté, synchronisation possible Mon apprentissage
Selectionner le thème
English

PlantUML : séquences, composants et déploiement en Java

Par mis à jour le

Améliorer cette page

PlantUML est le plus ancien et le plus complet des trois outils de diagramme as code en UML (le langage de modélisation standard) : séquence, composants, déploiement, classes. Il est écrit en Java, la plateforme d'exécution qu'il faut donc avoir pour le lancer. Cette leçon est facultative : si vous débutez, Mermaid et D2 suffisent. PlantUML reste le bon choix pour un projet qui en possède déjà, pour un UML détaillé, ou pour une équipe sur GitLab, qui le rend nativement. Vous le lancerez en conteneur, écrirez quatre diagrammes de la boutique en ligne et une vue C4, puis le brancherez à la CI.

  • Choisir PlantUML en connaissance de cause, licence comprise.
  • Rendre un fichier .puml en SVG avec une image épinglée.
  • Écrire contexte, séquence, composants, déploiement et une vue C4.
  • Contrôler la syntaxe et lire un code de retour.
  • Brancher l'ensemble dans un workflow de CI.

Le principe du diagramme as code, les chemins de rendu et le texte alternatif sont posés dans Diagrammes as code, que cette leçon ne répète pas. Le fil rouge est la boutique en ligne du modèle C4. Prérequis : Docker installé et un éditeur de texte.

Choisissez PlantUML dans trois cas : un projet existant en contient déjà des sources, vous voulez un UML détaillé (séquences riches, composants, déploiement, classes), ou votre équipe héberge son code sur GitLab. Sur GitLab.com, la documentation indique que PlantUML est actif « for all users, and requires no additional configuration ». En auto-hébergé, « a GitLab administrator must enable it » et la documentation GitLab recommande le serveur plantuml/plantuml-server:tomcat. GitHub, lui, ne rend pas PlantUML : il n'en figure pas parmi les quatre syntaxes qu'il affiche. Pour un nouveau projet sans contrainte, Mermaid ou D2 demandent moins d'outillage.

La licence mérite un coup d'œil. Le projet indique que PlantUML est distribué sous licence GPL par défaut (une licence libre qui impose de redistribuer les modifications sous la même licence). Un jar, l'archive Java exécutable de l'outil, existe aussi sous d'autres licences : GPLv2, LGPL, ASL, BSD, EPL, MIT (artefacts plantuml-asl-1.2026.8.jar, plantuml-bsd-1.2026.8.jar, etc.), plus un plantuml-java8-1.2026.8.jar pour Java 8. Le site précise que ces versions « miss few features (DITAA for example), but are 100% able to generate UML diagrams ». Si la GPL pose problème à votre organisation, une variante peut convenir.

Une particularité compte pour la sécurité de la chaîne d'approvisionnement : les jars sont signés (fichiers .asc), mais la release ne publie aucune somme SHA à comparer (constaté le 2026-10-13). On ne peut donc pas épingler le jar par empreinte comme on le fait pour D2. La parade est d'épingler l'image Docker par son digest, ce que fait la section suivante.

Le plus simple est l'image officielle, épinglée par tag et par digest (l'empreinte SHA-256 qui désigne une image de façon immuable). Elle embarque PlantUML, Java 21 et Graphviz, donc rien d'autre à installer. La commande écrit le rendu à côté de la source, et -u évite que les fichiers appartiennent à root.

Fenêtre de terminal
docker run --rm -u "$(id -u):$(id -g)" -v "$PWD:/data" \
plantuml/plantuml:1.2026.8@sha256:d08610df482510844382caa4e016ba2bf7e3231f630f02ee12f250f3416c62b1 \
-tsvg contexte.puml

Avec cette commande, contexte.svg apparaît à côté de la source (5 422 octets dans notre essai). L'option -tpng produit un PNG (1183 x 204 pour la même source), et -o rendu envoie les images dans le sous-dossier rendu. Pour vérifier l'installation, relancez la même commande en remplaçant la fin par -version : elle affiche PlantUML version 1.2026.8, la mention (GPL source distribution), un runtime OpenJDK, dot - graphviz version 14.0.1 et « Installation seems OK » (un avertissement sur libgvplugin_gd.so.8 peut précéder, sans effet sur le rendu SVG). Le code de retour est 0. L'option -testdot teste Graphviz seul.

Le jar en local (java -jar plantuml.jar -tsvg contexte.puml) est l'autre voie, mais elle n'a pas été testée sur le poste de rédaction, qui n'a pas Java : si vous la choisissez, vérifiez-la avec -version. PlantUML propose en outre une CLI bêta à doubles tirets (--svg, --check-syntax, --output-dir). Les options historiques à simple tiret, utilisées ici, restent valides.

La chaîne de rendu a une particularité : selon le type de diagramme, PlantUML délègue la mise en page à Graphviz (programme dot) ou la calcule lui-même (mise en page interne). Graphviz est un programme qui calcule la position des boîtes et des flèches. Le schéma ci-dessous montre ce choix : regardez les trois branches qui partent du jar vers l'image, et la voie pointillée par Smetana.

Chaîne de rendu PlantUML : une source .puml passe par plantuml.jar sur Java 21. Pour les classes, composants et déploiements, le jar appelle Graphviz dot ; pour les séquences et activités, sa mise en page interne ; en secours, Smetana, un dot porté en Java. Le résultat est un SVG ou un PNG. Un serveur PlantUML ou Kroki joue le même rôle derrière HTTP.Source .puml@startuml ... @endumlplantuml.jarsur Java 21Graphviz dot(classes, composants, déploiement)Smetana : dot porté en Java(pragma layout smetana)Séquence et activité :mise en page interneSVG ou PNGServeur PlantUML ou Kroki(même jar, derrière HTTP)
De la source .puml à l'image, avec ou sans Graphviz. Source · SVG
Échap pour fermer, + et − pour zoomer, défilement pour se déplacer. 100 %

La documentation de PlantUML liste ce qui exige Graphviz : les diagrammes de cas d'usage, de classes, d'objets et de composants, puis le déploiement, les états et les anciens diagrammes d'activité. Les séquences, absentes de cette liste, passent par la mise en page interne. Quand Graphviz manque, Smetana, une version de dot portée en Java, le remplace (!pragma layout smetana dans la source, ou -Playout=smetana en ligne de commande). Nous avons joué l'option en ligne de commande sur le diagramme de composants : rendu réussi, sans Graphviz. Le pragma n'a pas été rejoué.

La vue contexte de la boutique tient en cinq éléments : deux personnes, le système, et deux services externes. Dans la source ci-dessous, actor dessine une personne, rectangle "..." as alias un bloc nommé par un alias court, et --> une flèche suivie de : libellé. L'instruction left to right direction aligne le tout horizontalement.

@startuml
left to right direction
actor "Client" as client
actor "Gestionnaire de boutique" as gestionnaire
rectangle "Boutique en ligne" as boutique
rectangle "Service de paiement\n(externe)" as paiement
rectangle "Service de mail\n(externe)" as mail
client --> boutique : Consulte le catalogue et commande (HTTPS)
gestionnaire --> boutique : Gère le catalogue et les stocks (HTTPS)
boutique --> paiement : Débite la carte (JSON/HTTPS)
boutique --> mail : Envoie les e-mails de commande (SMTP)
@enduml

Voici le rendu réel produit par PlantUML 1.2026.8 : lisez les flèches depuis le client et le gestionnaire vers la boutique, puis de la boutique vers les deux services externes.

Vue contexte de la boutique : le client et le gestionnaire de boutique utilisent la boutique en ligne en HTTPS, qui débite la carte via le service de paiement en JSON/HTTPS et envoie les e-mails via le service de mail en SMTP.

La séquence est le point fort de PlantUML : elle montre qui appelle qui, dans quel ordre. Notre séquence « Passer une commande » compte neuf messages. autonumber les numérote, participant, actor et database déclarent les acteurs. La flèche -> est un appel plein, --> un retour en pointillé, ->> une flèche à tête fine, que la convention UML réserve au message asynchrone (l'émetteur n'attend pas de réponse). ++ après la cible active celle-ci, et return ferme l'activation avec sa réponse.

@startuml
title Passer une commande
autonumber
actor "Client" as client
participant "Interface web" as web
participant "API" as api
database "Base de données" as base
participant "Service de paiement" as paiement
participant "Service de mail" as mail
client -> web : Valide le panier
web -> api ++ : POST /commandes (JSON/HTTPS)
api -> base : Enregistre la commande « en attente »
api -> paiement ++ : Débite la carte
return Paiement accepté
api -> base : Passe la commande en « payée »
api ->> mail : Envoie la confirmation (SMTP)
return 201, commande créée
web --> client : Affiche la confirmation
@enduml

Dans le rendu, suivez les numéros de haut en bas. Les rectangles étroits sur les lignes de vie sont les activations ouvertes par ++ et refermées par return.

Séquence « Passer une commande » en neuf messages : le client valide le panier dans l'interface web, qui appelle l'API ; l'API enregistre la commande, débite la carte auprès du service de paiement, passe la commande en payée, envoie la confirmation au service de mail sans attendre, puis répond 201 à l'interface web, qui affiche la confirmation au client.

Ce n'est qu'un échantillon. La documentation des séquences ajoute alt / else / end pour un choix, loop pour une répétition, note over pour une remarque et activate / deactivate pour piloter les activations à la main.

Un composant est un bloc de code cohérent à l'intérieur d'un conteneur ; ce qu'il faut dessiner et où s'arrêter est expliqué dans Composants et code C4. Ici, le diagramme zoome dans le conteneur API. package regroupe les composants, [Nom] as alias en déclare un (un \n coupe le libellé sur deux lignes), database dessine la base, --> trace un appel et ..> une dépendance en pointillé. Il demande Graphviz, ou Smetana.

@startuml
left to right direction
title Composants du conteneur API
package "API (Node.js)" {
[Contrôleur HTTP\n(Express)] as controleur
[Service Catalogue] as catalogue
[Service Commandes] as commandes
[Client Paiement] as clientpaiement
[Notifications] as notifications
}
database "Base de données\n(PostgreSQL)" as base
[Service de paiement\n(externe)] as paiement
[Service de mail\n(externe)] as mail
controleur --> catalogue : Transmet les demandes de catalogue
controleur --> commandes : Transmet les commandes
catalogue --> base : Lit (SQL/TCP)
commandes --> base : Lit et écrit (SQL/TCP)
commandes --> clientpaiement : Demande le débit
commandes --> notifications : Demande la confirmation
clientpaiement --> paiement : Débite la carte (JSON/HTTPS)
notifications --> mail : Envoie les e-mails (SMTP)
@enduml

Le rendu ci-dessous place le cadre « API (Node.js) » autour des cinq composants : repérez que seuls Client Paiement et Notifications sortent vers l'extérieur. La syntaxe offre aussi les interfaces (()) et les note, absentes de cet exemple.

Composants du conteneur API : le contrôleur HTTP transmet aux services Catalogue et Commandes ; le service Commandes lit et écrit dans PostgreSQL et sollicite le client de paiement et les notifications, qui appellent respectivement le service de paiement et le service de mail.

Le diagramme de déploiement dit où tourne chaque morceau, ce que détaille la vue de déploiement C4. Les node s'imbriquent (un poste contient un navigateur, qui contient l'interface), artifact désigne le livrable, database la base et cloud un service tiers. L'imbrication se lit comme une arborescence : le premier niveau est la machine, le suivant l'environnement d'exécution, le dernier ce qui y est installé.

@startuml
left to right direction
title Déploiement en production
node "Poste du client" {
node "Navigateur web" {
artifact "Interface web" as web
}
}
node "Serveur applicatif\n(Ubuntu 24.04, x2)" {
node "Node.js 22" {
artifact "API" as api
}
}
node "Serveur de données\n(Ubuntu 24.04)" {
node "PostgreSQL 17" {
database "Base de données" as base
}
}
cloud "Service de paiement\n(externe)" as paiement
cloud "Service de mail\n(externe)" as mail
web --> api : Appelle (JSON/HTTPS)
api --> base : Lit et écrit (SQL/TCP)
api --> paiement : Débite la carte (JSON/HTTPS)
api --> mail : Envoie les e-mails (SMTP)
@enduml

Dans l'image, vérifiez que l'API est sur deux serveurs applicatifs (le x2 du libellé) et que la base reste sur une machine dédiée.

Déploiement en production : l'interface web dans le navigateur du poste client appelle l'API de Node.js 22 sur deux serveurs applicatifs Ubuntu 24.04 ; l'API lit et écrit dans PostgreSQL 17 sur un serveur de données Ubuntu 24.04, débite la carte via le service de paiement et envoie les e-mails via le service de mail, deux nuages externes.

C4-PlantUML est une bibliothèque de macros qui fournit le vocabulaire du C4 (Person, System, Rel…). Elle est embarquée dans PlantUML : la commande -stdlib y relève la version 2.13.0 (licence MIT), et !include <C4/C4_Context>, avec des chevrons, la charge sans réseau. Person, System et System_Ext déclarent les boîtes, Rel(from, to, label, techn) une relation. Pour le niveau suivant, Container et ContainerDb prennent le relais.

@startuml
!include <C4/C4_Context>
title Contexte de la boutique en ligne
Person(client, "Client", "Parcourt le catalogue, passe commande")
Person(gestionnaire, "Gestionnaire de boutique", "Met à jour le catalogue et les stocks")
System(boutique, "Boutique en ligne", "Vend le catalogue et encaisse les commandes")
System_Ext(paiement, "Service de paiement", "Encaisse les cartes bancaires")
System_Ext(mail, "Service de mail", "Envoie les e-mails transactionnels")
Rel(client, boutique, "Consulte le catalogue et commande", "HTTPS")
Rel(gestionnaire, boutique, "Gère le catalogue et les stocks", "HTTPS")
Rel(boutique, paiement, "Débite la carte", "JSON/HTTPS")
Rel(boutique, mail, "Envoie les e-mails de commande", "SMTP")
@enduml

Le rendu respecte la charte C4 : les boîtes externes sont grises, chaque flèche porte son libellé et sa technologie.

Contexte C4 de la boutique en ligne, rendu par C4-PlantUML : le client et le gestionnaire de boutique utilisent la boutique en ligne en HTTPS ; la boutique débite la carte via le service de paiement externe en JSON/HTTPS et envoie les e-mails via le service de mail externe en SMTP.

Kroki sait aussi rendre cette source sur son point d'entrée /c4plantuml/svg. Cette bibliothèque décrit un fichier par vue, sans modèle partagé. Pour garder plusieurs vues cohérentes, voir C4 en code, qui compare Structurizr, Mermaid C4 et C4-PlantUML.

Comment contrôler la syntaxe et lire une erreur ?

Section intitulée « Comment contrôler la syntaxe et lire une erreur ? »

Avant de rendre, on vérifie la source. -checkonly contrôle la syntaxe sans rien écrire : sur contexte.puml, il ne dit rien et rend le code 0. Les codes de retour sont documentés : 0 pour un succès, 50 si aucun fichier n'est trouvé, 100 si aucun diagramme n'est trouvé, 200 pour une erreur de syntaxe. Voici une source volontairement cassée, casse.puml.

@startuml
actor "Client" as client
participant "Interface web" as web
client -> web : Valide le panier
web -> api : POST /commandes
client ->web Affiche la confirmation
@enduml

Sur ce fichier, -checkonly affiche Some diagram description contains errors et rend le code 200. Un rendu normal (-tsvg casse.puml) signale Error line 6, et la ligne 6 est bien la fautive : il manque : avant le libellé de client ->web Affiche la confirmation.

Un piège compte pour la CI : malgré l'erreur, PlantUML écrit quand même casse.svg (1 971 octets), une image d'erreur. Testez donc le code de retour, jamais la présence du fichier. -failfast2 fait une passe de contrôle avant tout rendu (No diagram found, aucune image produite), et -failfast s'arrête à la première erreur.

Une limite : un package jamais fermé (accolade } oubliée) passe -checkonly avec le code 0, car PlantUML tolère l'accolade manquante et ferme le groupe tout seul. Aucun message ne signale l'oubli : seule la relecture de la source et de l'image permet de voir quels éléments se retrouvent dans le package. Passé par Kroki, le même casse.puml renvoie Error 400: Syntax Error? (Assumed diagram type: sequence) (line: 5) : Kroki compte sans la ligne @startuml, d'où 5 au lieu de 6.

Comment rendre le diagramme compréhensible sans l'image ?

Section intitulée « Comment rendre le diagramme compréhensible sans l'image ? »

PlantUML n'écrit aucune balise de titre ni de description de schéma dans le SVG : ni <title> ni <desc>. Le lecteur d'écran n'a donc rien à lire : le texte alternatif de l'image et la phrase qui la précède portent toute l'information. La méthode est exposée dans Diagrammes as code et dans Montrer, pas seulement décrire.

Dans la CI, on rejoue les mêmes commandes sur l'image épinglée : d'abord -checkonly, qui échoue sur une erreur, puis -tsvg. Voici l'étape PlantUML d'un workflow GitHub Actions. Le workflow complet donne permissions: {} au niveau global, contents: read au job, et persist-credentials: false au checkout (action épinglée sur son commit, version en commentaire).

name: Diagrammes
on:
pull_request:
paths:
- "docs/**/*.puml"
permissions: {}
jobs:
rendre:
runs-on: ubuntu-24.04
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: PlantUML, syntaxe puis rendu
run: |
docker run --rm -u "$(id -u):$(id -g)" -v "$PWD:/data" \
plantuml/plantuml:1.2026.8@sha256:d08610df482510844382caa4e016ba2bf7e3231f630f02ee12f250f3416c62b1 \
-checkonly docs/**/*.puml
docker run --rm -u "$(id -u):$(id -g)" -v "$PWD:/data" \
plantuml/plantuml:1.2026.8@sha256:d08610df482510844382caa4e016ba2bf7e3231f630f02ee12f250f3416c62b1 \
-tsvg docs/**/*.puml

Ce workflow a passé actionlint et zizmor (aucun constat). Les commandes docker run ont été jouées sur le poste, mais le workflow lui-même n'a pas été exécuté sur un runner GitHub. Le glob docs/**/*.puml est développé par le shell du runner, bash par défaut, où ** équivaut à * tant que shopt -s globstar n'a pas été activé : docs/**/*.puml devient docs/*/*.puml, qui ne trouve que les fichiers d'un sous-dossier direct de docs/, ni ceux posés directement dans docs/, ni ceux de niveaux plus profonds. Avec shopt -s globstar, tous sont trouvés. Activez l'option ou listez les fichiers avec find, et testez le résultat sur votre dépôt.

Sans Docker, un serveur peut rendre à la place du jar : Kroki (la requête POST /plantuml/svg a répondu HTTP 200 sur les versions 0.30 et 0.33) ou plantuml/plantuml-server (non testé). Le choix entre ces chemins est expliqué dans Diagrammes as code. Dans un projet AsciiDoc, Asciidoctor Diagram appelle PlantUML au moment de la conversion, voir le guide AsciiDoc.

Exercice guidé : comment écrire la séquence « Annuler une commande » ?

Section intitulée « Exercice guidé : comment écrire la séquence « Annuler une commande » ? »

À vous d'appliquer la syntaxe. Créez annulation.puml pour décrire ce scénario dans l'ordre :

  1. Client → Interface web : « Demande l'annulation ».
  2. Interface web → API : DELETE /commandes/{id}.
  3. API → Base de données : « Passe la commande en annulée ».
  4. API → Service de paiement : « Rembourse la carte », réponse « Remboursement accepté ».
  5. API → Service de mail : « Envoie l'avis d'annulation », sans attendre de réponse.
  6. API → Interface web : « 200 ».
  7. Interface web → Client : « Affiche la confirmation ».

Avant de regarder le corrigé, vérifiez trois points : les messages sont numérotés (autonumber), l'appel au service de paiement ouvre puis ferme une activation (++ puis return), et l'envoi du mail est asynchrone (->>). Rendez le fichier, puis lancez -checkonly.

@startuml
title Annuler une commande
autonumber
actor "Client" as client
participant "Interface web" as web
participant "API" as api
database "Base de données" as base
participant "Service de paiement" as paiement
participant "Service de mail" as mail
client -> web : Demande l'annulation
web -> api ++ : DELETE /commandes/{id} (JSON/HTTPS)
api -> base : Passe la commande en « annulée »
api -> paiement ++ : Rembourse la carte
return Remboursement accepté
api ->> mail : Envoie l'avis d'annulation (SMTP)
return 200
web --> client : Affiche la confirmation
@enduml

Si le rendu échoue, relisez le message : il cite la ligne fautive, le plus souvent un : oublié avant le libellé.

  • PlantUML couvre séquence, composants, déploiement et classes ; il est facultatif si Mermaid ou D2 suffisent.
  • GitLab le rend nativement sur GitLab.com ; GitHub ne le rend pas.
  • Licence GPL par défaut, jars aussi sous d'autres licences ; pas de somme SHA publiée, donc on épingle l'image Docker par digest.
  • Graphviz est nécessaire pour composants, déploiement et classes, pas pour la séquence ; Smetana le remplace en secours.
  • C4-PlantUML est embarquée (!include <C4/C4_Context>) mais décrit un fichier par vue, sans modèle partagé.
  • -checkonly contrôle sans rendre : code 0 si tout va bien, 200 sur erreur de syntaxe.
  • Un rendu en erreur écrit quand même une image : en CI, lisez le code de retour, pas la présence du fichier.
  • Un package non fermé passe -checkonly : relisez l'image.
  • Le SVG n'a ni <title> ni <desc> de schéma : le texte alternatif de la page porte tout.

Contrôle de connaissances

Validez vos connaissances avec ce quiz interactif

6 questions
6 min.
70% requis

Informations

  • Le chronomètre démarre au clic sur Démarrer
  • Questions à choix multiples, vrai/faux et réponses courtes
  • Vous pouvez naviguer entre les questions
  • Les résultats détaillés sont affichés à la fin

Lance le quiz et démarre le chronomètre

Ce projet vous est utile ?

Les guides, formations, quiz et labs restent gratuits. Si vous les utilisez régulièrement, vous pouvez contribuer à leur maintenance et à leur développement.

Devenir membre de soutien (nouvel onglet) Soutenir une fois (nouvel onglet) En savoir plus

Suivez aussi le projet sur LinkedIn