Plugin REST
Controllers, DTOs et dérivation HTTP automatique.
Référence complète du plugin REST HexaGlue : génération de controllers Spring MVC, DTOs avec validation, et dérivation automatique des verbes HTTP depuis les ports driving.
Ajouter le plugin REST
<plugin> <groupId>io.hexaglue</groupId> <artifactId>hexaglue-maven-plugin</artifactId> <version>6.1.1</version> <extensions>true</extensions> <configuration> <basePackage>com.acme.shop</basePackage> </configuration> <dependencies> <dependency> <groupId>io.hexaglue.plugins</groupId> <artifactId>hexaglue-plugin-rest</artifactId> <version>3.1.1</version> </dependency> </dependencies></plugin>La génération s'exécute automatiquement lors de la phase generate-sources (mvn compile). Les artefacts sont générés dans target/generated-sources/hexaglue/.
Le plugin analyse les ports driving (interfaces de cas d'utilisation) et génère pour chacun un controller REST complet avec DTOs et validation.
<extensions>true</extensions>: active le binding automatique aux phases Maven. Les goals HexaGlue se déclenchent sans configuration supplémentaire lors demvn compile.<basePackage>: package racine à analyser. Le plugin REST découvre automatiquement les ports driving de ce package et de ses sous-packages.- Le plugin REST est déclaré comme
<dependency>du plugin Maven, pas du projet. HexaGlue le découvre automatiquement viaServiceLoader.
Le plugin REST se combine naturellement avec les plugins JPA et Audit. HexaGlue exécute d'abord les générateurs (REST, JPA), puis l'audit valide l'architecture complète.
Le plugin génère du code qui utilise Spring MVC et Bean Validation. Ajoutez ces dépendances à votre pom.xml :
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> <!-- Optionnel : documentation OpenAPI --> <dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId> <version>2.8.6</version> </dependency></dependencies>Paramètres Maven
<configuration> du plugin Maven dans le pom.xml.Ces paramètres contrôlent le package analysé, le répertoire de sortie et le comportement en cas de types non classifiés.
Le paramètre
skip peut aussi être passé en ligne de commande via -Dhexaglue.skip=true.| Option | Défaut |
|---|---|
basePackage | (requis) |
failOnUnclassified | false |
outputDirectory | /generated-sources/hexaglue |
skip | false |
skipValidation | false |
tolerantResolution | false |
Options YAML
hexaglue.yaml, placé à la racine du projet (à côté du pom.xml), centralise la configuration de HexaGlue et de tous ses plugins.Les options ci-dessous se configurent dans la section
plugins.io.hexaglue.plugin.rest: du fichier YAML.Les paramètres Maven (
<configuration>) sont prioritaires sur les valeurs YAML.| Option | Type | Défaut |
|---|---|---|
controllerSuffix | string | Controller |
requestDtoSuffix | string | Request |
responseDtoSuffix | string | Response |
basePath | string | /api |
exceptionHandlerClassName | string | GlobalExceptionHandler |
apiPackage | string | (auto-détecté) |
targetModule | string | (auto-détecté) |
generateOpenApiAnnotations | boolean | true |
flattenValueObjects | boolean | true |
generateExceptionHandler | boolean | true |
generateConfiguration | boolean | true |
exceptionMappings | map | (vide) |
Ce qui est généré pour chaque port driving
| Artefact | Exemple (OrderUseCases) |
|---|---|
| Controller | OrderController |
| Request DTO | CreateOrderRequest |
| Response DTO | OrderResponse |
| Exception Handler | GlobalExceptionHandler |
| Configuration | RestConfiguration |
Les identifiants de type wrapper (comme record OrderId(UUID value)) sont automatiquement dépliés vers leur type primitif dans les DTOs et les @PathVariable. L'identifiant est reconstruit via la factory OrderId.of(uuid) dans le controller.
Les artefacts sont organisés en sous-packages : controller, dto, exception et config. Le package parent est configurable via apiPackage.
Des signatures de méthode aux endpoints REST
| Préfixe | Verbe | Chemin | Statut |
|---|---|---|---|
create, add, register | POST | / | 201 |
get, find, load | GET | /{id} | 200 |
getAll, list, findAll | GET | / | 200 |
search, query | GET | /search | 200 |
update, modify, edit | PUT | /{id} | 200 |
delete, remove, archive | DELETE | /{id} | 204 |
count | GET | /count | 200 |
exists, is, has | GET | /{id}/exists | 200 |
| (autre commande avec identifiant) | POST | /{id}/{action} | 200/204 |
Le plugin résout automatiquement les collisions d'URL. Si deux méthodes produisent le même verbe et chemin, l'une d'elles est préfixée avec le nom de la méthode en kebab-case. Un avertissement est émis dans les logs Maven.
Les méthodes de type query (retournant une valeur sans effet de bord) sont mappées sur GET. Les méthodes de type command (modifiant l'état) sont mappées sur POST, PUT ou DELETE selon le préfixe. Les commandes retournant void reçoivent le statut 204.
Code généré
Order.Controller
@RestController@RequestMapping("/api/orders")@Tag(name = "Orders", description = "Order management operations")public class OrderController {
private final OrderUseCases orderUseCases;
public OrderController(OrderUseCases orderUseCases) { this.orderUseCases = orderUseCases; }
@PostMapping @Operation(summary = "Create order") public ResponseEntity<Object> createOrder( @Valid @RequestBody CreateOrderRequest request) { var result = orderUseCases.createOrder(request.customerId(), ...); return ResponseEntity.status(201).body(OrderResponse.from(result)); }
@GetMapping("/{id}") @Operation(summary = "Get order") public ResponseEntity<Object> getOrder(@PathVariable UUID id) { var result = orderUseCases.getOrder(OrderId.of(id)); return ResponseEntity.ok(OrderResponse.from(result)); }}Request et Response DTOs
// Request DTO : validation automatique depuis les types du domainepublic record CreateOrderRequest( @NotNull UUID customerId, @NotBlank String productName, @Positive int quantity) {}
// Response DTO : factory from() pour la projection domaine → RESTpublic record OrderResponse( UUID id, UUID customerId, String productName, String status) { public static OrderResponse from(Order source) { return new OrderResponse( source.getId().value(), source.getCustomerId().value(), source.getProductName(), source.getStatus().name()); }}Exception Handler
@RestControllerAdvicepublic class GlobalExceptionHandler {
@ExceptionHandler(IllegalArgumentException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public Map<String, Object> handleIllegalArgument( IllegalArgumentException ex) { return Map.of( "error", "BAD_REQUEST", "message", ex.getMessage(), "status", 400); }
@ExceptionHandler(Exception.class) @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) public Map<String, Object> handleException(Exception ex) { return Map.of( "error", "INTERNAL_SERVER_ERROR", "message", ex.getMessage(), "status", 500); }}Configuration
La classe @Configuration expose les application services via leurs ports driving, permettant à Spring d'injecter automatiquement les implémentations dans les controllers.
@Configurationpublic class RestConfiguration {
@Bean public OrderUseCases orderUseCases(OrderService orderService) { return orderService; }}Routage des artefacts en multi-module
- 1Configuration explicite :
targetModule: "shop-api"danshexaglue.yaml - 2Auto-routage par convention : si un seul module a le rôle
API, les artefacts y sont routés automatiquement - 3Défaut : si ni configuration ni convention ne s'appliquent, les artefacts sont écrits dans le répertoire de sortie par défaut
Si plusieurs modules ont le rôle API et qu'aucun targetModule n'est configuré, le plugin émet un avertissement et utilise le répertoire de sortie par défaut. Préférez la configuration explicite dans ce cas.
modules: shop-core: role: DOMAIN shop-api: role: API shop-persistence: role: INFRASTRUCTURE
plugins: io.hexaglue.plugin.rest: targetModule: "shop-api" basePath: "/api/v2"Configuration complète
hexaglue.yaml. En pratique, seules les options dont vous souhaitez modifier la valeur par défaut sont nécessaires.plugins: io.hexaglue.plugin.rest: # Package cible (auto-détecté si omis) apiPackage: "com.acme.shop.api"
# Suffixes de nommage controllerSuffix: "Controller" requestDtoSuffix: "Request" responseDtoSuffix: "Response"
# URL de base basePath: "/api"
# Annotations OpenAPI (@Tag, @Operation, @ApiResponse) generateOpenApiAnnotations: true
# Aplatir les value objects multi-champs dans les DTOs flattenValueObjects: true
# Handler d'exceptions global (@RestControllerAdvice) generateExceptionHandler: true exceptionHandlerClassName: "GlobalExceptionHandler"
# Classe @Configuration avec @Bean pour les ports generateConfiguration: true
# Mappings exception → HTTP status personnalisés exceptionMappings: "com.acme.shop.OrderNotFoundException": 404 "com.acme.shop.InsufficientStockException": 409
# Multi-module (optionnel) # targetModule: "shop-api"Besoin d'une génération sur mesure ?
Ce plugin couvre les patterns d'API REST les plus courants, mais chaque entreprise a ses propres conventions et exigences techniques. L'architecture ouverte d'HexaGlue vous permet de créer des plugins adaptés à votre stack.
Concentrez-vous sur les cas d'utilisation.
Générez les controllers en quelques lignes.
Définissez vos ports driving, HexaGlue génère les endpoints REST avec validation et documentation OpenAPI.