Architecture hexagonale et
Spring / Spring Boot
1. Introduction
L’architecture hexagonale (aussi appelée Ports & Adapters) est un modèle
d’architecture logicielle qui vise à découpler le cœur métier (le domaine) des
détails techniques (base de données, protocoles, UI, API, etc.).
Ce type d’architecture est parfaitement adapté à des projets modernes en Java
avec Spring ou Spring Boot, en particulier ceux utilisant des microservices,
des files de messages (comme RabbitMQ), ou des bases NoSQL comme
MongoDB.
2. Objectifs de l’architecture hexagonale
Indépendance vis-à-vis des frameworks, des bases de données et des
protocoles d’entrée/sortie
Testabilité accrue du code métier
Flexibilité pour changer de technologie (ex : changer MongoDB par
PostgreSQL)
Lisibilité et responsabilités claires dans la structure du projet
3. Vue générale (structure logique)
graph TD;
A["Adapter entrant<br/>(ex: REST, AMQP)"] -->|appelle| B["Port Entrant<
br/>(interface)"];
B -->|définit| C((Domaine<br/>et business logic<br/>core métier ));
C -->|utilise| D["Port Sortant<br/>(interface)"];
D -->|implémente| E["Adapter sortant<br/>(MongoDB, SMTP, etc)"];
Adapter entrant (ou user side) : comment le monde extérieur
interagit avec notre application
Architecture hexagonale et Spring / Spring Boot 1
L'adapter entrant, également désigné par le terme « user side » représente la
passerelle entre le monde extérieur et l’application, permettant ainsi une
interaction fluide et sécurisée avec les données et fonctionnalités de cette
dernière.
Définition
Un adapter entrant est un composant logiciel qui gère la réception des requêtes
venant de sources externes. Il sert d'interface entre les utilisateurs (humains ou
systèmes) et les services internes de l'application. Il peut s'agir d'interfaces
utilisateur graphiques (UI), d'API REST, de WebSocket, ou même de systèmes
de messagerie.
Rôles principaux
Gestion des requêtes utilisateur : Il traite les actions des utilisateurs, telles
que les clics, les soumissions de formulaire, ou les appels d'API.
Validation des données : Il vérifie la conformité des données entrantes
avant qu'elles n'atteignent la logique métier.
Sécurité : Il gère l'authentification et l'autorisation pour protéger
l'application contre les accès non autorisés.
Transformation des données : Il adapte les données externes au format
attendu par l’application interne.
Bonnes pratiques
Séparer la logique métier de la logique de présentation : L'adapter entrant
ne doit pas contenir de logique métier complexe.
Assurer la résilience : Gérer les erreurs et les exceptions de manière
efficace.
Optimiser la sécurité : Implémenter des contrôles d'accès robustes et des
validations de données strictes.
Exemples
Interface utilisateur (UI) : Applications web, mobiles, ou desktop.
API REST/GraphQL : Permettent aux applications tierces de communiquer
avec votre système.
Webhooks : Utilisés pour recevoir des notifications d'événements
provenant de services externes.
Architecture hexagonale et Spring / Spring Boot 2
Systèmes de messagerie : Kafka, RabbitMQ pour des communications
asynchrones.
Adapter
Rôle
entrant
Reçoit les requêtes HTTP depuis une application frontend ou un
REST controller
système externe.
RabbitMQ
Écoute les messages AMQP et déclenche les use cases.
listener
Adapter sortant (ou server side) : comment notre application
utilise le monde extérieur
Un adapter sortant, aussi appelé adapter côté serveur, c’est un peu comme un
pont entre votre application et d’autres systèmes. Il facilite la communication et
l’échange de données, ce qui est super important pour le bon fonctionnement
de votre application.
Définition et rôle
Un adapter sortant est le composant logiciel qui permet à une application
d’interagir avec des services externes tels que des API tierces, des bases de
données distantes, des services web ou d’autres systèmes d’information. Il agit
comme un traducteur entre les protocoles internes de l’application et ceux des
services externes.
Fonctionnement
Lorsqu’une application a besoin d’envoyer des données ou de récupérer des
informations à partir d’un système externe, l’adapter sortant prend en charge :
1. La transformation des données : il convertit les données dans un format
compatible avec le système ciblé.
2. La gestion des protocoles de communication : il assure la compatibilité
entre les protocoles utilisés par l’application (par exemple HTTP, FTP,
SOAP, REST) et ceux des services externes.
3. La sécurité des échanges : il peut intégrer des mécanismes
d’authentification et de chiffrement pour garantir la confidentialité et
l’intégrité des données.
Avantages des adapters sortants
Architecture hexagonale et Spring / Spring Boot 3
Flexibilité : ils permettent d’intégrer facilement de nouveaux services
externes sans modifier l’architecture interne.
Maintenance simplifiée : les changements nécessaires pour s’adapter à
des évolutions des systèmes externes peuvent être réalisés uniquement au
niveau de l’adapter.
Sécurité renforcée : ils centralisent la gestion des échanges, facilitant ainsi
le contrôle des flux de données.
Exemples d’utilisation
Une application e-commerce qui communique avec un service de paiement
en ligne via un adapter sortant pour traiter des transactions.
Un système de gestion d’inventaire qui interagit avec des fournisseurs
externes pour mettre à jour automatiquement les niveaux de stock.
Une application mobile qui se connecte à une API météo pour afficher des
prévisions en temps réel.
Adapter
Rôle
sortant
MongoDB
Stocke ou lit des données depuis une base de données NoSQL
repository
SMTP mail
Envoie des notifications par email
sender
AMQP
Publie des messages vers un exchange/topic
producer
HTTP REST
Appelle une API externe
client
Ce sont des outils utilisés par le domaine (via les interfaces des ports
sortants) pour réaliser un use case.
4. Terminologie clé
Élément Rôle
Domaine Contient les règles métier, les entités, et les cas d’usage
Interfaces qui décrivent comment interagir avec le domaine (ex:
Ports entrants
ProcessSensorDataUseCase)
Architecture hexagonale et Spring / Spring Boot 4
Élément Rôle
Interfaces que le domaine utilise pour interagir avec des services
Ports sortants
externes (ex: SensorDataPersistencePort)
Adaptateurs Implémentations des ports entrants (ex: contrôleurs REST, listeners
entrants RabbitMQ)
Adaptateurs Implémentations techniques des ports sortants (ex: accès MongoDB,
sortants envoi d’emails)
5. Illustration avec notre projet
Pour illustrer correctement les trois zones (User-Side, Business Logic, Server-
Side), cette application reçoit les données de capteurs depuis un système
extérieur (ici RabbitMQ), les traite, puis les stocke dans une base de données
(MongoDB).
Architecture hexagonale et Spring / Spring Boot 5
L’architecture Hexagonale n’hérite pas directement de l’architecture DDD, mais
peut typiquement l’embarquer en son centre (ici regroupé dans la “business
logic”, comprenant le domaine et la couche business qui applique les règles
métiers.
6. Application des principes
User-Side
Dans notre cas, les adaptateurs entrants incluent :
une API REST qui expose des rapports ou des informations consolidées,
un listener RabbitMQ qui reçoit des mesures brutes.
Ces adaptateurs pilotent la logique métier via des interfaces comme
ProcessSensorDataUseCase .
Business Logic
Le cœur de l’application contient :
les entités (ex: SensorReading ),
les cas d’usage (ex: ProcessSensorDataService ),
les ports sortants (ex: SensorDataPersistencePort , AlertNotifierPort ).
Server-Side
Les adaptateurs sortants implémentent ces ports pour interagir avec :
MongoDB (via MongoSensorDataAdapter ),
SMTP ou RabbitMQ Producer pour les alertes,
un autre système externe si besoin.
Dépendances vers l’intérieur
Tous les adaptateurs dépendent du domaine. Le domaine ne dépend de rien.
7. Structure projet exemple
src/
├── domain/
Architecture hexagonale et Spring / Spring Boot 6
│ ├── model/
│ │ └── [Link]
│ ├── ports/
│ │ ├── in/
│ │ │ └── [Link]
│ │ └── out/
│ │ └── [Link]
│ └── usecase/
│ └── [Link]
│
├── adapters/
│ ├── in/
│ │ ├── rest/
│ │ │ └── [Link]
│ │ └── amqp/
│ │ └── [Link]
│ └── out/
│ └── mongo/
│ └── [Link]
│
├── config/
│ └── [Link]
└── [Link]
8. Bonnes pratiques
Toujours injecter des interfaces (ports), pas des classes concrètes.
Ne jamais inclure de logiques métiers dans les adaptateurs.
Ne jamais utiliser une classe d’infrastructure dans le domaine.
Privilégier les DTO pour les communications externes.
9. Conclusion
Les remarques courantes concernant la mise en place d’un projet basé sur une
architecture sont :
C’est long à mettre en place.
Architecture hexagonale et Spring / Spring Boot 7
C’est coûteux. Il faut créer des objets dans le domaine, des modèles, etc.
Cependant, cette architecture répond à différents besoins. Elle améliore
notamment la pérennité, la maintenabilité et la testabilité du projet. Le temps
initialement investi sera rapidement récupéré, et la confiance dans le projet
sera grandement renforcée.
L’architecture hexagonale permet de créer des applications bien structurées,
testables et évolutives. Elle s’intègre naturellement avec Spring ou Spring Boot.
Elle est particulièrement adaptée aux contextes de microservices et de
traitement d’événements, comme dans notre projet SensorHub.
Architecture hexagonale et Spring / Spring Boot 8