---
title: Applications Mule et flows
description: De quoi est faite une app Mule, comment un Mule event traverse un flow, ce qu’On Error Propagate et On Error Continue renvoient au client, et comment Flow Reference, Choice, Scatter-Gather et For Each changent le chemin. Cinq schémas animés et un quiz de trois questions.
date: 2026-10-21
level: Beginner
tags: MuleSoft, Mule 4, flows, gestion des erreurs
---

Une app Mule est un ensemble de flows, et un flow est le chemin que suit un Mule event, d’une source jusqu’à la fin. Comprenez bien ces deux idées et le reste de Mule 4 devient beaucoup plus simple : les error handlers, les routers, et même la raison pour laquelle votre payload a disparu après un appel HTTP.

Cette leçon suit une petite app de commandes à travers cinq schémas animés. Chacun s’anime tout seul dès qu’il est à l’écran. Les boutons au-dessus changent l’histoire : faire tomber l’API de stock, changer d’error handler, choisir un router. Mettez-le en pause quand vous voulez et avancez pas à pas avec les flèches.

## Une app, plusieurs flows

Une app Mule est livrée sous la forme d’un seul JAR. Les flows vivent dans des fichiers XML sous `src/main/mule`, à côté d’un `pom.xml` et d’un `mule-artifact.json` qui liste ces fichiers. Ce JAR se déploie sur CloudHub 2.0, sur Runtime Fabric ou sur un runtime Mule installé sur vos propres serveurs.

Les flows ne possèdent pas leurs connexions. Un global element, comme une config HTTP Listener ou une config Database, est déclaré une seule fois, et tous les flows de l’app pointent dessus. Tout ce qui change d’un environnement à l’autre va dans un property placeholder comme `${http.port}`, pas dans le XML.

<figure class="lab" data-lab="app" data-desc="L’app de commandes : deux flows, post-order lancé par une requête HTTP et nightly-report lancé par un Scheduler, qui utilisent tous deux des global elements partagés pour le listener HTTP, l’API de stock et la base de données.">
</figure>

Chaque flow démarre depuis sa propre source. post-order attend une requête, nightly-report attend 02:00. Ils partagent de la configuration, jamais un event.

## Ce qui circule, c’est le Mule event

Tout ce que fait un flow, il le fait sur un Mule event. L’event a deux parties : le message, c’est-à-dire un payload plus des attributes, et les variables.

- `payload`, ce sont les données. Pour une requête HTTP, c’est le corps.
- `attributes` disent d’où viennent les données : méthode, chemin, en-têtes, paramètres de requête.
- `vars` sont à vous. Set Variable les écrit, et elles restent avec l’event pour tout le reste du flow.

Le piège : presque tous les processors renvoient un nouveau message. Appelez une autre API avec HTTP Request et sa réponse devient le payload, son code de statut atterrit dans les attributes, et la commande envoyée par le client a disparu. Sauf si vous avez d’abord gardé ce dont vous avez besoin dans une variable, ou demandé à l’appel de ranger son résultat ailleurs avec `target`.

<figure class="lab" data-lab="event" data-desc="Une commande qui traverse post-order : le HTTP Listener transforme la requête en Mule event, Set Variable garde le SKU, et le HTTP Request soit remplace le payload par la réponse du stock, soit, avec target=&quot;stock&quot;, la range dans vars.stock et laisse le message inchangé.">
</figure>

Passez à `target="stock"` et regardez la ligne du payload. Cette fois, elle ne clignote pas à l’étape HTTP Request : la réponse atterrit dans `vars.stock`, et la commande est toujours le payload quand le listener répond. Le Logger, dans les deux cas, ne change rien.

## Les erreurs prennent un autre chemin

Quand un processor échoue, Mule lève une erreur d’un type comme `HTTP:CONNECTIVITY`, saute le reste du flow et passe à l’error handler du flow. Le handler exécute le premier On-Error dont le type correspond. Il en existe deux sortes, et elles répondent au client de façon très différente.

- On Error Propagate exécute ses processors, puis relance l’erreur. Le HTTP Listener répond 500 avec la description de l’erreur comme corps. Le payload posé dans le handler n’est pas envoyé, sauf si vous configurez la réponse d’erreur du listener.
- On Error Continue exécute ses processors, puis termine le flow comme un succès. Le listener répond 200 avec le payload, quel qu’il soit.

Et si le flow n’a aucun handler, le handler par défaut de Mule logge l’erreur et la propage.

<figure class="lab" data-lab="errors" data-desc="post-order appelle l’API de stock. Quand l’API est en ligne, le flow se termine par un 200. Quand elle est en panne, le HTTP Request lève HTTP:CONNECTIVITY : avec On Error Propagate, le client reçoit un 500 avec la description de l’erreur ; avec On Error Continue, il reçoit un 200 avec le payload de repli du handler.">
</figure>

Lancez « en panne » avec On Error Continue et regardez le résultat : l’API de stock est en panne et le client reçoit un 200. Parfois, c’est exactement ce que vous voulez : une réponse de repli. Si le client doit savoir que quelque chose a échoué, fixez le code de statut vous-même.

## Flow Reference : sub-flow ou flow

Flow Reference appelle un autre flow de la même app avec le même event. Les variables voyagent avec lui, donc le flow appelé peut lire `vars.sku`, et le payload qu’il laisse derrière lui devient celui de l’appelant au retour. Ce que vous appelez peut prendre deux formes.

- Un sub-flow n’a ni source ni error handler. Mule met ses processors à la place du Flow Reference quand il construit l’app : il fait vraiment partie de l’appelant.
- Un flow sans source peut avoir son propre error handler. Une erreur à l’intérieur va d’abord à ce handler, et n’atteint l’appelant que si le handler la propage.

<figure class="lab" data-lab="flowref" data-desc="post-order appelle check-stock avec un Flow Reference. Si check-stock est un sub-flow et que l’appel au stock échoue, c’est l’error handler de post-order qui s’exécute, et le client reçoit un 500. Si check-stock est un flow avec son propre handler On Error Continue, c’est ce handler qui s’exécute, le Flow Reference rend la main normalement et post-order répond 200.">
</figure>

Donc, quand check-stock a son propre On Error Continue, post-order ne voit jamais l’échec. Son Flow Reference rend simplement la main et le Logger s’exécute. Parfait pour un repli, et facile à rater quand vous lisez les logs en vous demandant pourquoi le handler de l’appelant est resté muet.

## Routers et scopes changent le chemin

Un flow n’est pas forcément une ligne droite.

- Choice teste ses routes dans l’ordre et exécute la première dont la condition est vraie. Si aucune ne l’est, c’est la route `otherwise` qui s’exécute ; elle est facultative.
- Scatter-Gather envoie l’event à toutes les routes en même temps, chacune sur son propre thread, et les attend toutes. Le résultat est un seul payload avec une clé par route : `0`, `1` et ainsi de suite.
- For Each exécute ses processors une fois par élément d’une collection. Il ne change pas le payload : après la boucle, vous récupérez l’original. Les variables posées dans la boucle restent posées.

<figure class="lab" data-lab="routers" data-desc="Trois flows. Un router Choice envoie une commande vers la route Nantes pour FR, la route New Jersey pour US, et vers un Raise Error dans la route otherwise pour tout autre pays. Un Scatter-Gather appelle l’API de stock et l’API de prix en même temps et renvoie un seul objet aux clés 0 et 1. Un For Each réserve le stock une fois par article de la commande et laisse le payload tel quel : la commande d’origine.">
</figure>

Scatter-Gather est le bon réflexe quand deux appels ne dépendent pas l’un de l’autre : le devis attend l’appel le plus lent, pas les deux à la suite. Si une route échoue, Mule attend quand même les autres, puis lève `MULE:COMPOSITE_ROUTING`, avec à l’intérieur ce qui a échoué et ce qui a marché.

## Vérifiez vos acquis

Trois questions sur ce que vous venez de faire tourner. Choisissez une réponse pour en voir l’explication.

<ol class="quiz" aria-label="Vérifiez vos acquis">
<li data-answer="1"><p class="quiz-q">Le HTTP Request de post-order a <code>target="stock"</code>. Après son exécution, que contient le payload ?</p><ul class="quiz-options"><li>La réponse de l’API de stock</li><li>La commande envoyée par le client</li><li>Rien : le payload est vidé</li></ul><details class="quiz-why" id="quiz-why-1"><summary>Réponse</summary><p>La commande envoyée par le client. Avec <code>target</code>, le résultat de l’appel va dans <code>vars.stock</code> et le message passe sans changer.</p></details></li>
<li data-answer="2"><p class="quiz-q">L’API de stock est en panne, et l’error handler de post-order est un On Error Continue avec un Set Payload. Que reçoit le client ?</p><ul class="quiz-options"><li>Un 500 avec la description de l’erreur</li><li>Aucune réponse</li><li>Un 200 avec le payload du handler</li></ul><details class="quiz-why" id="quiz-why-2"><summary>Réponse</summary><p>Un 200 avec le payload du handler. On Error Continue termine le flow comme un succès, donc le listener répond comme si rien n’avait échoué.</p></details></li>
<li data-answer="0"><p class="quiz-q">post-order appelle check-stock avec un Flow Reference. check-stock est un sub-flow, et l’appel au stock qu’il contient échoue. Quel error handler s’exécute ?</p><ul class="quiz-options"><li>L’error handler de post-order</li><li>L’error handler propre à check-stock</li><li>Aucun : les sub-flows ignorent les erreurs</li></ul><details class="quiz-why" id="quiz-why-3"><summary>Réponse</summary><p>Celui de post-order. Un sub-flow n’a pas d’error handler : ses processors s’exécutent à la place du Flow Reference, donc l’erreur va au handler de l’appelant, ou à un scope Try autour du Flow Reference.</p></details></li>
</ol>

## D’où viennent les faits

Chaque affirmation de cette leçon a été vérifiée dans la documentation de Mule 4 :

- [Développement d’apps Mule](https://docs.mulesoft.com/mule-runtime/latest/mule-app-dev) et [global elements](https://docs.mulesoft.com/mule-runtime/latest/global-elements)
- [Le Mule event](https://docs.mulesoft.com/mule-runtime/latest/about-mule-event) et [target variables](https://docs.mulesoft.com/mule-runtime/latest/target-variables)
- [Gestion des erreurs](https://docs.mulesoft.com/mule-runtime/latest/error-handling), [scopes On-Error](https://docs.mulesoft.com/mule-runtime/latest/on-error-scope-concept) et la [référence du HTTP Listener](https://docs.mulesoft.com/http-connector/latest/http-listener-ref)
- [Flows et sub-flows](https://docs.mulesoft.com/mule-runtime/latest/about-flows) et [Flow Reference](https://docs.mulesoft.com/mule-runtime/latest/flowref-about)
- [Choice](https://docs.mulesoft.com/mule-runtime/latest/choice-router-concept), [Scatter-Gather](https://docs.mulesoft.com/mule-runtime/latest/scatter-gather-concept) et [For Each](https://docs.mulesoft.com/mule-runtime/latest/for-each-scope-concept)
- [Options de déploiement](https://docs.mulesoft.com/mule-runtime/latest/deploying)

C’est la base sur laquelle s’appuie le reste du parcours. Prochaine étape : les watermarks, ou comment un flow de polling se souvient de l’endroit où il s’est arrêté. Si un schéma fait quelque chose que Mule ne ferait pas, dites-le-moi. Les liens de contact sont juste en dessous.
