Brahim Bousnguar

Cours · MuleSoft · Leçon 1 sur 8

Applications Mule et flows

Par · · 7 min de lecture · 5 labs interactifs

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.

Lab 1 · Une app, deux flows

App déployée

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.

Ce qui lance un flow

Global elements · partagés par tous les flows

  1. HTTP Listener configport ${http.port}
  2. HTTP Request configstock-api · ${stock.host}
  3. Database configorders-db

flow post-order

  1. HTTP ListenerPOST /orders
  2. HTTP RequestGET /stock/{sku}
  3. Loggercommande reçue

flow nightly-report

  1. Schedulertous les jours à 02:00
  2. Databasecommandes de la veille
  3. Loggerligne du rapport

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.

Lab 2 · Le Mule event, pas à pas

Requête reçue

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="stock", la range dans vars.stock et laisse le message inchangé.

Le résultat de l’appel au stock va dans

flow post-order

  1. HTTP ListenerPOST /orders
  2. Set Variablesku = #[payload.sku]
  3. HTTP RequestGET /stock/#[vars.sku]
  4. Logger#[payload]

Événement Mule

payload
{ "sku": "SOFA-D5", "qty": 1 }
attributes
method: "POST"
requestPath: "/orders"
headers: { "content-type": "application/json", … }
queryParams: {}
vars
(aucune pour l’instant)

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.

Lab 3 · Quand l’API de stock tombe

Requête reçue

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.

API de stock
Error handler

flow post-order

  1. HTTP ListenerPOST /orders
  2. Set Variablesku
  3. HTTP RequestGET /stock/#[vars.sku]
  4. Loggercommande reçue

error handler

  1. On Error Propagatetype: ANY
  2. Set Payload{ message: "Stock check failed" }

Événement Mule

payload
{ "sku": "SOFA-D5", "qty": 1 }
vars
(aucune pour l’instant)

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.

Lab 4 · Flow Reference : sub-flow ou flow

Requête reçue

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.

check-stock est
API de stock

flow post-order

  1. HTTP ListenerPOST /orders
  2. Set Variablesku
  3. Flow Referencecheck-stock
  4. Loggercommande reçue

sub-flow check-stock · sans source, sans error handler

  1. HTTP RequestGET /stock/#[vars.sku]

error handler de post-order

  1. On Error Propagatetype: ANY

Événement Mule

payload
{ "sku": "SOFA-D5", "qty": 1 }
vars
(aucune pour l’instant)

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.

Lab 5 · Routers et scopes

Commande reçue

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.

Choisissez
Pays de la commande

flow route-order

  1. HTTP ListenerPOST /orders
  2. Choiceby payload.country

    country == "FR"

    1. HTTP Requestentrepôt de Nantes

    country == "US"

    1. HTTP Requestentrepôt du New Jersey

    otherwise

    1. Raise ErrorAPP:UNSUPPORTED_COUNTRY
  3. Loggerroutée

Événement Mule

payload
{ "orderId": "A-1042", "country": "FR", "sku": "SOFA-D5" }
vars
(aucune pour l’instant)

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.

  1. Le HTTP Request de post-order a target="stock". Après son exécution, que contient le payload ?

    • La réponse de l’API de stock
    • La commande envoyée par le client
    • Rien : le payload est vidé
    Réponse

    La commande envoyée par le client. Avec target, le résultat de l’appel va dans vars.stock et le message passe sans changer.

  2. 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 ?

    • Un 500 avec la description de l’erreur
    • Aucune réponse
    • Un 200 avec le payload du handler
    Réponse

    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é.

  3. 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 ?

    • L’error handler de post-order
    • L’error handler propre à check-stock
    • Aucun : les sub-flows ignorent les erreurs
    Réponse

    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.

D’où viennent les faits

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

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.

Texte brut: mule-app-flows.md · Tous les parcours

Contact

Écrivez-moi.

b.bousnguar@gmail.com

Intégration SAP Commerce Cloud, MuleSoft et Salesforce · Nantes · FR / EN