Aller au contenu

SEMAINE 5a - JOUR 1 – JPA/HIBERNATE, VALIDATION, GESTION GLOBALE DES ERREURS & TEST DES ENDPOINTS

Formation Java / Spring Boot – Qualité API & outils professionnels


Objectifs

À l’issue de cette journée, vous serez capable de :


PARTIE 1 – MAPPING AVEC JPA/HIBERNATE (ORM)

Mapping avec Hibernate

Nous avons déjà découvert les bases du Mapping la semaine dernière. Nous allons approfondir certains concepts.


PARTIE 2 – VALIDATION DES DONNÉES (BEAN VALIDATION)

1) Pourquoi valider les entrées ?

Sans validation :

Une API professionnelle valide les données dès l’entrée, voire même dès le front-end dans certaine configuration.


2) Introduction à Bean Validation

Spring Boot intègre Hibernate Validator.

Ajouter dépendance si nécessaire :

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

3) Création d’un DTO validé

On ne valide pas les entités directement, on valide les DTO d’entrée.

public record CompteCreationDTO(

    @NotBlank(message = "Le numéro est obligatoire")
    String numero,

    @NotNull(message = "Le solde initial est obligatoire")
    @Positive(message = "Le solde doit être positif")
    BigDecimal solde

) {}

4) Activation de la validation dans le contrôleur

@PostMapping
public ResponseEntity<?> creerCompte(
        @Valid @RequestBody CompteCreationDTO dto) {

    service.creerCompte(dto);
    return ResponseEntity.ok().build();
}

@Valid déclenche automatiquement la validation.


5) Exemple d’erreur retournée (sans gestion personnalisée)

Si le JSON est invalide :

{
  "solde": -100
}

Spring retourne une erreur 400 avec les détails. Nous allons dans la suite, contrôler la structure de cette erreur.


PARTIE 2 – GESTION GLOBALE DES ERREURS

Lien vers une explication sur l’intérêt ou pas d’utiliser un @ControllerAdvice

6) Problème sans gestion globale

Dans une application professionnelle, on contrôle les réponses.


7) Création d’un @ControllerAdvice

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(IllegalArgumentException.class)
    public ResponseEntity<?> handleIllegalArgument(
            IllegalArgumentException ex) {

        return ResponseEntity
                .badRequest()
                .body(Map.of("error", ex.getMessage()));
    }
}

8) Gestion des erreurs de validation

@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<?> handleValidationErrors(
        MethodArgumentNotValidException ex) {

    Map<String, String> errors = new HashMap<>();

    ex.getBindingResult().getFieldErrors()
        .forEach(error ->
            errors.put(error.getField(), error.getDefaultMessage()));

    return ResponseEntity.badRequest().body(errors);
}

Résultat propre

Le JSON retourne les messages d’erreur liés à la saisie.

{
  "numero": "Le numéro est obligatoire",
  "solde": "Le solde doit être positif"
}

C’est Lisible et Structuré.


PARTIE 3 – DOCUMENTATION AVEC SWAGGER (OPENAPI)

Même si vous n’allez pas l’utiliser, il est intéressant de le découvrir et le tester. Vous le connaissez déjà, du coup, on utilisera Bruno pour changer.

9) Pourquoi Swagger ?

Ajouter la dépendance sanchant que la version peut varier :

<dependency>
  <groupId>org.springdoc</groupId>
  <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
  <version>2.3.0</version>
</dependency>

URL :

http://localhost:8080/swagger-ui.html

10) Annotation d’un endpoint

@Operation(summary = "Créer un compte bancaire")
@PostMapping
public ResponseEntity<?> creerCompte(
        @Valid @RequestBody CompteCreationDTO dto) {
    ...
}

Swagger génère automatiquement :


PARTIE 4 – TEST DES ENDPOINTS AVEC BRUNO


11) Qu’est-ce que Bruno ?

Bruno est un outil moderne pour :

Bruno fonctionne avec des fichiers .bru. Les requêtes peuvent être versionnées dans Git.

Site officiel : https://www.usebruno.com/


12) Installation de Bruno

  1. Télécharger Bruno
  2. Installer localement
  3. Créer une nouvelle collection

13) Création d’une requête dans Bruno

Exemple : GET liste comptes

Créer un fichier list-comptes.bru

meta {
  name: Liste comptes
  type: http
  seq: 1
}

get {
  url: http://localhost:8080/api/comptes
}

14) Exemple POST avec JSON

meta {
  name: Créer compte
  type: http
  seq: 2
}

post {
  url: http://localhost:8080/api/comptes
  body: json
}

body:json {
  {
    "numero": "FR100",
    "solde": 500
  }
}

15) Avantages de Bruno


PARTIE 5 – COMPARAISON SWAGGER VS BRUNO

Swagger Bruno
Documentation Test manuel
Généré automatiquement Requêtes manuelles
Interface web Fichiers versionnés
Exploration Validation scénarios

Les deux sont complémentaires.


PARTIE 6 – TRAVAUX PRATIQUES JOUR 19


TP 1 – Validation complète sur un de vos projets


TP 2 – Gestion globale des erreurs


TP 3 – Swagger


TP 4 – Collection Bruno versionnée


16) Erreurs fréquentes

  1. Valider les entités au lieu des DTO
  2. Ignorer @Valid
  3. Ne pas gérer les exceptions globalement
  4. Exposer les stacktraces
  5. Confondre Swagger et outil de test
  6. Ne pas versionner les requêtes Bruno
  7. Tester uniquement les cas positifs
  8. Ignorer les codes HTTP
  9. Retourner 200 pour une erreur
  10. Ne pas relire les messages d’erreur

17) État de votre projet

Maintenant, vous devez avoir réalisé :


Synthèse

Vous savez maintenant :


Swagger et data.sql

Pour gagner du temps, générez vos entités depuis votre BD (avec Eclipse) car pour IntelliJ, il faut la version entreprise.

Projet JPA et génération des entities

Projets de démonstration sur GitHub