Aller au contenu

Semaine 5a : JOUR 2 – REQUETES JPQL - MQ AVEC SPRING BOOT (RABBITMQ)

Formation Java / Spring Boot – Architecture asynchrone & découplage


Objectifs

Hier, nous avons vu JPA/Hibernate avec Spring et cette journée sera découpée en 2 parties :

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

Aujourd’hui, après avoir abordé le JPQL pour compléter la journée d’hier, on verra ensuite comment passer du monolithe REST à une architecture orientée événements !


PARTIE 1 – JPQL & Spring Data JPA avec PostgreSQL (approfondissement)

Lien vers le cours complet sur JPQL & Spring Data

PARTIE 2 – POURQUOI UTILISER UN MESSAGE BROKER ?


1) Problème du REST pur (synchrone)

Avec REST :

Exemple :

Un virement déclenche :

Si tout est REST en mode synchrone :


2) Solution : architecture événementielle

Le principe :

  1. L’action principale s’exécute
  2. Un événement est publié
  3. D’autres services réagissent

PARTIE 3 – CONCEPTS MQ


3) Message Broker (fournisseur)

Un Message Broker :

Exemples :

Nous utilisons RabbitMQ.


4) Concepts fondamentaux RabbitMQ


5) Architecture simple

[Votre API] --> (Exchange) --> [Queue] --> [Consumer Service]

PARTIE 4 – INSTALLATION RABBITMQ

Il est possible que nous n’utilisions pas Docker. Nous aviserons en fonction de ce qui se fait chez CA-Titres

Docker (recommandé)

docker run -d --hostname rabbit \
  -p 5672:5672 \
  -p 15672:15672 \
  rabbitmq:3-management

Interface web :

http://localhost:15672

Login par défaut :


PARTIE 5 – CONFIGURATION AVEC SPRING BOOT


Dépendance

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

Configuration application.properties

spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest

PARTIE 6 – EXEMPLE CONCRET


Cas métier

Lors d’un virement :

Un service externe :


PARTIE 7 – DÉFINITION DES COMPOSANTS MQ


6.1 Configuration Rabbit

@Configuration
public class RabbitConfig {

    @Bean
    public Queue virementQueue() {
        return new Queue("virement.queue");
    }

    @Bean
    public TopicExchange exchange() {
        return new TopicExchange("banque.exchange");
    }

    @Bean
    public Binding binding(Queue queue, TopicExchange exchange) {
        return BindingBuilder
            .bind(queue)
            .to(exchange)
            .with("virement.*");
    }
}

6.2 Publisher (Producer)

@Service
public class VirementPublisher {

    private final RabbitTemplate rabbitTemplate;

    public VirementPublisher(RabbitTemplate rabbitTemplate) {
        this.rabbitTemplate = rabbitTemplate;
    }

    public void publierVirement(VirementEvent event) {
        rabbitTemplate.convertAndSend(
            "banque.exchange",
            "virement.effectue",
            event
        );
    }
}

6.3 Event avec DTO

public record VirementEvent(
    String numeroSource,
    String numeroCible,
    BigDecimal montant
) {}

6.4 Consumer

@Component
public class VirementListener {

    @RabbitListener(queues = "virement.queue")
    public void traiterVirement(VirementEvent event) {
        System.out.println("Audit virement : " + event);
    }
}

PARTIE 8 – INTÉGRATION DANS UN SERVICE MÉTIER


Dans VirementService :

@Transactional
public void virer(...) {
    // logique métier
    publisher.publierVirement(event);
}

Le REST retourne immédiatement, l’audit est asynchrone.


PARTIE 9 – TEST AVEC BRUNO


  1. Appel POST /api/virement
  2. Vérifier mise à jour comptes
  3. Vérifier message dans RabbitMQ
  4. Vérifier console du listener

PARTIE 10 – AVANTAGES EN CONTEXTE BANCAIRE


Exemples réels :

MQ permet :


PARTIE 11 – TRAVAUX PRATIQUES


TP 1 – Implémentation basique MQ


TP 2 – Simulation panne Consumer


TP 3 – Gestion erreur Consumer

Ajouter :

throw new RuntimeException("erreur test");

Observer le comportement.


TP 4 – Création d’un second consumer


PARTIE 12 – ERREURS FRÉQUENTES

  1. Publier dans le contrôleur
  2. Mettre logique métier dans le consumer
  3. Oublier transactions
  4. Mauvaise configuration exchange
  5. Ne pas gérer idempotence
  6. Ignorer les retries
  7. Confondre MQ et REST
  8. Ne pas monitorer Rabbit
  9. Messages trop lourds
  10. Pas de logs

Synthèse

Vous savez maintenant :


On abordera