Aller au contenu

Semaine 4 : JOUR 2 – ARCHITECTURE SPRING BOOT & PREMIÈRES API REST

Formation Java / Spring Boot – Montée en puissance technique


Objectifs

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

À partir d’aujourd’hui, on construit une vraie application backend.

Swagger, un outil bien pratique

Pour tester facilement les endpoints, vos URI, vous pouvez intégrer Swagger dans votre application Spring Boot.

Swagger et data.sql


Architecture Spring Boot – Vue d’ensemble

Architecture cible standard

com.banque
├── BanqueApplication.java
├── controller
│   └── CompteController.java
├── service
│   └── CompteService.java
├── repository
│   └── CompteRepository.java
├── domain (ou model ou entity)
│   └── Compte.java
│   └── CompteCourant.java
│   └── CompteEpargne.java
└── exception
    └── DebitInterditException.java

Cette architecture est :


Rôle précis de chaque couche (fondamental)

Controller

Service

Repository

Domaine


Cycle de vie d’une requête HTTP

  1. Le client envoie une requête HTTP
  2. Spring identifie le contrôleur
  3. Spring appelle la méthode correspondante
  4. Le contrôleur appelle le service (et récupère les données si c’est prévu)
  5. Le service exécute la logique métier
  6. Une réponse est construite
  7. Spring renvoie la réponse HTTP

Tout est automatique, mais pas magique.


Création du premier contrôleur REST

Annotation clé : @RestController

@RestController
@RequestMapping("/api/comptes")
public class CompteController {
}

@RestController = @Controller + @ResponseBody

Les objets retournés sont automatiquement convertis au format JSON.


Premier endpoint : GET simple

Objectif

@GetMapping("/ping")
public String ping() {
    return "Banque API is running...";
}

Test :


Retourner un objet métier (JSON automatique)

@GetMapping("/exemple")
public Compte exemple() {
    return new CompteEpargne("FR001", new BigDecimal("1000"));
}

Spring transforme l’objet Java en JSON comme ci-dessous :

{
  "numero": "FR001",
  "solde": 1000
}

Pourquoi en JSON, tout simplement parce que c’est le format (clef -> Valeur) le plus utilisé et le plus facile à exploiter pour la partie Front (VueJS, Angular, React). Nous verrons qu’avec Thymeleaf, on peut s’en passer car il peut manipuler des objets Java.


Injection du service dans le contrôleur

@RestController
@RequestMapping("/api/comptes")
public class CompteController {

    private final CompteService service;

    public CompteController(CompteService service) {
        this.service = service;
    }
}

Ici, on fait une Injection par constructeur, c’est-à-dire, on passe le service comme argument dans le constructeur et Spring Boot se charge de l’instancier ! On pourrait aussi le faire en utilisant une simple annotation @Autowired dans la déclaration sans avoir de passer ce service dans comme argument, mais ce n’est plus une bonne pratique et cela rend les tests unitaires difficiles.


Création du service métier

@Service
public class CompteService {

    private final CompteRepository repository;

    public CompteService(CompteRepository repository) {
        this.repository = repository;
    }

    public List<Compte> listerComptes() {
        return repository.findAll();
    }
}

Remarquez que nous utilisons le même principe d’injection dans le contrôleur en passant le Repository.


Repository (version temporaire en mémoire)

@Repository
public class CompteRepository {

    private final Map<String, Compte> stockage = new HashMap<>();

    public List<Compte> findAll() {
        return new ArrayList<>(stockage.values());
    }

    public void save(Compte compte) {
        stockage.put(compte.getNumero(), compte);
    }

    public Compte findByNumero(String numero) {
        return stockage.get(numero);
    }
}

Cette implémentation sera remplacée par JPA plus tard et le reste du code ne changera PAS. Souvenez-vous de DAO avec le concepts des Interfaces. C’est exactement la même chose ici.


Endpoint GET – Liste des comptes

On ajoute une annotation pour chaque méthode du Controller. L’appel à l’url permettra d’exécuter la méthode qui correspond.

@GetMapping("/api/comptes")
public List<Compte> lister() {
    return service.listerComptes();
}

Testez l’url GET /api/comptes


Endpoint POST – Création d’un compte

Comprendre @RequestBody

@PostMapping
public void creerCompte(@RequestBody Compte compte) {
    service.creerCompte(compte);
}

Spring :


Exemple JSON envoyé

{
  "numero": "FR002",
  "solde": 500
}

Ajout de la méthode côté service

Dans le service, le code métier et donc le nom des méthodes est différent de celles du Repository.

public void creerCompte(Compte compte) {
    repository.save(compte);
}

Gestion des paramètres d’URL – @PathVariable

Lorsque l’on reçoit des paramètres (variables), on les récupère en précisant que ce sont des *variables dans l’url** avec l’annotation @PathVariable.

@GetMapping("/{numero}")
public Compte getCompte(@PathVariable String numero) {
    return service.trouverCompte(numero);
}

Gestion des erreurs – première approche

Problème

Nous devons traiter ce problème avec des Exceptions.


Solution simple (temporaire)

public Compte trouverCompte(String numero) {
    Compte compte = repository.findByNumero(numero);
    if (compte == null) {
        throw new IllegalArgumentException("Désolé, compte introuvable !");
    }
    return compte;
}

La gestion HTTP fine viendra plus tard avec @ControllerAdvice.


Travaux pratiques


TP 1 – Création d’une API complète

Consignes :

  1. Créer un contrôleur REST
  2. Exposer :
    • liste des comptes ou autre suivant le projet sur lequel vous travaillez
    • création d’un compteou autre
    • consultation par numéro ou autre
  3. Tester via navigateur

TP 2 – Séparation stricte des responsabilités

Objectif : Reprendre du code d’un précédent TP et réorganiser votre code :


TP 3 – Enrichissement métier

Consignes :


TP 4 – Nettoyage et refactorisation

Consignes :


16) Erreurs fréquentes

  1. Mettre la logique métier dans le contrôleur
  2. Utiliser @RestController comme fourre-tout
  3. Créer des endpoints trop verbeux
  4. Ne pas tester l’API manuellement
  5. Mélanger HTTP et métier
  6. Ignorer les codes HTTP
  7. Modifier directement les objets exposés
  8. Coupler contrôleur et repository
  9. Ne pas relire les routes
  10. Penser que “ça marche” suffit

Objectif sur le projet en cours

À ce stade :


Synthèse de la journée

Vous savez maintenant :


La prochaine fois, on abordera :

On passe de l’API stateless à l’API persistante.