Pourquoi le Tomcat embarqué ne suffit pas avec Jakarta Faces
Le symptôme est déroutant : l'application démarre sans erreur, les journaux sont propres, et le navigateur affiche le code source de la page au lieu de la page. Aucune exception, aucun avertissement.
Ce qui se passe réellement
Le serveur embarqué démarré par spring-boot:run ne suit pas le même
chemin d'initialisation qu'un serveur d'applications autonome. Il ignore le
descripteur de déploiement, et surtout il n'explore pas les archives des
bibliothèques à la recherche de ce qu'elles déclarent.
Or c'est précisément ainsi que Jakarta Faces s'installe : son implémentation annonce sa servlet dans un fragment de descripteur enfoui dans son archive. Sans cette exploration, la servlet n'est jamais enregistrée. La requête arrive alors sur le service de fichiers statiques, qui fait ce pour quoi il est fait : il renvoie le fichier tel quel.
D'où l'absence d'erreur. Rien n'a échoué — la page n'a simplement jamais été confiée au moteur censé la traiter.
La conséquence pratique
Une application qui associe Spring Boot et Jakarta Faces se déploie en archive web sur un serveur autonome. Ce n'est pas une préférence d'architecture, c'est une condition de fonctionnement.
Le corollaire est net : mvn spring-boot:run cesse d'être une commande de
développement utile sur ce type de projet. Il vaut mieux le savoir dès le
premier jour que le découvrir au bout de trois heures.
La leçon plus générale
L'absence d'erreur n'est pas un signe de bon fonctionnement. Ici, chaque composant a rempli son rôle correctement ; c'est l'enchaînement attendu qui n'a jamais eu lieu. Ces défauts-là ne se trouvent pas dans les journaux, mais en se demandant qui était censé traiter la requête, et en vérifiant que ce composant a bien été enregistré.