+33 6 74 52 84 16 contact@lmvi.eu

Plongée dans les APIs Registry de WSO2 Micro Integrator !

Salut les passionnés de l’intégration ! Aujourd’hui, avec notre ami Marius, on embarque pour un voyage au cœur des APIs Registry du WSO2 Micro Integrator. Que vous soyez un développeur chevronné ou un grand amateur de technologie, cet article est fait pour vous.

Bonjour !

Je suis Jean-Marc HENRY, ingénieur ESI,  consultant IT/IS pour les entreprises depuis plus de 35 ans, et fondateur de LMVI Conseil.

À travers ce blog, je vous propose d’explorer ensemble tous les 15 jours les grands ou petits (!) sujets de l’informatique.

Ici, on parlera de sujets qui me servent quotidiennement et qui me tiennent à cœur, comme le Nocode, l’IA, l’IT, l’IS ou l’architecture logicielle et un peu WSO2.

D’ailleurs, je ne suis pas seul à rédiger ces billets !

Je suis accompagné de mon assistant IA prénommé Marius. C’est un bon pote d’Ollama et de ChatGPT (entre autres, car il a un sacré réseau !).

Il est assez secret et ne me dit pas tout sur la manière dont il m’aide à écrire mes articles. En revanche, je ne publie rien qui n’ait été validé par des sources sûres ou testé !

C’est parti, on vous embarque !

1 Pourquoi s’intéresser aux APIs Registry ?

Imaginez que vous ayez une baguette magique 🪄 pour lire et écrire des données de configuration en temps réel dans votre intégration. C’est exactement ce que permettent les APIs Registry du WSO2 Micro Integrator.

Elles sont particulièrement utiles pour des scénarios comme le Change Data Capture (CDC) avec le pattern Database Polling.

Dans cet article, je vous explique comment fonctionnent ces deux APIs, les cas de figure les plus rencontrés , et la spécificité de leur gestion des espaces de noms (« namespace ») et des emplacements (« where ») dans le registre.

C’est parti, on décortique tout ça ensemble. 🕵️‍♂️

Marius : « Une API capable de manipuler dynamiquement les données de configuration, ça ouvre de belles perspectives pour les architectes logiciels ! »

2 Les super-pouvoirs des APIs

2.1 L’API de Lecture

Cette API est votre détective privé 🕵️‍♀️. Elle va chercher la valeur associée à une clé spécifique dans le registre. Voici comment elle opère :

  • Construction dynamique du chemin : elle assemble le chemin d’accès en concaténant :
    • Le paramètre where (l’emplacement dans le registre, comme gov, conf ou local) ;
    • Le namespace (espace de noms) ;
    • La clé.
  • Lecture de la valeur : grâce au médiateur personnalisé RegistryReadHandlerMediator, elle récupère la valeur à ce chemin.
  • Réponse : si tout se passe bien, elle vous renvoie une réponse JSON contenant la valeur et les détails du chemin.

Marius : « J’adore le concept de lecture dynamique. Cela évite d’avoir à déployer de nouvelles configurations manuellement ! »

2.2 L’API d’Écriture

Besoin d’inscrire une nouvelle donnée ? Cette API est votre plume numérique 🖋️. Elle sauvegarde une valeur dans le registre avec les mêmes paramètres de chemin en suivant ces étapes :

  • Extraction de la valeur : elle prélève la valeur du payload JSON de votre requête.
  • Écriture dans le registre : avec l’aide du médiateur RegistryWriteHandlerMediator, elle écrit cette valeur à l’endroit désigné dans le registre.
  • Confirmation : en cas de succès, elle vous retourne une réponse JSON confirmant l’écriture avec tous les détails du chemin.

Marius : « L’automatisation de l’écriture dans un registre, combinée à des API REST, c’est une solution idéale pour rendre les systèmes plus réactifs et adaptables ! »

3 Le paramètre « where » : votre GPS dans le registre

Le paramètre where est essentiel. C’est lui qui définit où les opérations de lecture ou d’écriture ont lieu dans le registre. Voici les principaux emplacements :

  1. gov (Governance Registry) : pour les valeurs partagées au niveau de la gouvernance. Dans le contexte du pattern « Database Polling », c’est ici que l’on stocke des infos comme le dernier timestamp de synchronisation CustomIE/timestamp.
  2. conf (Configuration Registry) : utilisé pour stocker les configurations applicatives.
  3. local : pour les données locales spécifiques à une instance ou un serveur.

4 Pattern Database Polling et Registry : un duo gagnant.

Dans le cadre du CDC (« Change Data Capture »), WSO2 Micro Integrator utilise souvent un mécanisme appelé « Database Polling ». Cette technique interroge régulièrement la base de données pour détecter d’éventuels changements. La dernière synchronisation est alors enregistrée dans le registre, généralement sous :

  • Emplacement : gov
  • Chemin : CustomIE/timestamp

Ainsi, lors de la prochaine interrogation, le système sait exactement où reprendre. 🎯


5 Exemples pratiques

5.1 Lecture d’une valeur

Envie de savoir ce qui se cache derrière une clé ? Voici comment faire :


curl -X GET "http://:/registryReadAPI/read/gov/CustomIE/timestamp" -H "Accept: application/json"

Réponse JSON possible :


{
"namespace": "CustomIE",
"key": "timestamp",
"value": "2024-12-12T10:00:00Z"
}

5.2 Écritures d’une valeur.

Besoin de mettre à jour une information ? C’est très simple :

curl -X POST "http://<your-server-host>:<port>/registryWriteAPI/write/gov/CustomIE/timestamp" \
-H "Content-Type: application/json" \
-d '{
"value": "2024-12-13T10:00:00Z"
}'{ "namespace": "CustomIE", "key": "timestamp", "value": "2024-12-12T10:00:00Z" }

Et en retour, vous obtenez :

{
"status": "success",
"message": "Value written successfully",
"details": {
"namespace": "CustomIE",
"key": "timestamp",
"value": "2024-12-13T10:00:00Z",
"path": "gov:CustomIE/timestamp"
}
}

6. Conclusion

Ces deux APIs facilitent la gestion des valeurs dans le registre du Micro Integrator WSO2. Elles permettent de manipuler efficacement les données de gouvernance, de configuration et locales, en particulier dans des scénarios comme le « Change Data Capture ». En utilisant le paramètre where, les développeurs peuvent cibler précisément les emplacements souhaités.

Les APIs Registry de WSO2 Micro Integrator sont des outils puissants pour gérer dynamiquement vos configurations et données.

Que ce soit pour le « Database Polling » ou le « Change Data Capture », elles offrent une flexibilité et une efficacité remarquables. En utilisant le paramètre where, vous pourrez cibler précisément les emplacements souhaités

Alors, prêt à les intégrer dans vos projets ? 🚀

N’hésitez pas à partager vos expériences ou à poser des questions en commentaire. À la prochaine pour de nouvelles aventures technologiques ! 👋

RegistryReadAPIHandler

<?xml version="1.0" encoding="UTF-8"?>
<api context="/registryReadAPI" name="RegistryReadAPIHandler" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="GET" uri-template="/read/{where}/{namespace}/{key}">
<inSequence>
<!-- Log d'entrée -->
<log level="custom">
<property name="Step" value="Entering RegistryReadAPI"/>
<property expression="get-property('uri.var.namespace')" name="Namespace"/>
<property expression="get-property('uri.var.key')" name="Key"/>
</log>
<!-- Construire dynamiquement le chemin du registre -->
<property expression="fn:concat(get-property('uri.var.where'),':', get-property('uri.var.namespace'), '/', get-property('uri.var.key'))" name="registryPath" scope="default" type="STRING"/>
<log level="custom">
<property name="Step" value="Registry Path Resolved"/>
<property expression="get-property('registryPath')" name="RegistryPath"/>
</log>
<!-- Appeler le médiateur personnalisé -->
<class name="org.wso2.custom.mediators.RegistryReadHandlerMediator"/>
<!-- Log pour confirmer la valeur -->
<log level="custom">
<property name="Step" value="Post Custom Mediator"/>
<property expression="$ctx:registryValue" name="RegistryValue"/>
</log>
<!-- Vérifier et envoyer la réponse -->
<filter regex=".*" source="$ctx:registryValue">
<then>
<log level="custom">
<property name="Step" value="Responding with registry value"/>
</log>
<payloadFactory media-type="json">
<format>
{
"namespace": "$1",
"key": "$2",
"value": "$3"
}
</format>
<args>
<arg evaluator="xml" expression="get-property('uri.var.namespace')"/>
<arg evaluator="xml" expression="get-property('uri.var.key')"/>
<arg evaluator="xml" expression="$ctx:registryValue"/>
</args>
</payloadFactory>
</then>
<else>
<log level="custom">
<property name="Step" value="No value found in registry"/>
</log>
<payloadFactory media-type="json">
<format>
{
"status": "error",
"message": "No value found for registry path: $1"
}
</format>
<args>
<arg evaluator="xml" expression="get-property('registryPath')"/>
</args>
</payloadFactory>
</else>
</filter>
<property name="messageType" scope="axis2" type="STRING" value="application/json"/>
<respond/>
</inSequence>
<outSequence>
<log level="custom">
<property name="Step" value="Exiting RegistryReadAPI"/>
</log>
</outSequence>
<faultSequence>
<log level="full">
<property name="Step" value="Fault Occurred"/>
</log>
<payloadFactory media-type="json">
<format>
{
"status": "error",
"message": "An error occurred while processing the request."
}
</format>
<args/>
</payloadFactory>
<property name="messageType" scope="axis2" type="STRING" value="application/json"/>
<respond/>
</faultSequence>
</resource>
</api>

RegistryWriteAPIHandler

<?xml version="1.0" encoding="UTF-8"?>
<api context="/registryWriteAPI" name="RegistryWriteAPIHandler" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="POST" uri-template="/write/{where}/{namespace}/{key}">
<inSequence>
<property name="messageType" scope="axis2" type="STRING" value="application/json"/>
<log level="custom">
<property name="Step" value="Entering RegistryWriteAPI"/>
<property expression="get-property('uri.var.namespace')" name="Namespace"/>
<property expression="get-property('uri.var.key')" name="Key"/>
<property expression="json-eval($)" name="Payload"/>
</log>
<property expression="fn:concat(get-property('uri.var.where'),':', get-property('uri.var.namespace'), '/', get-property('uri.var.key'))" name="registryPath" scope="default" type="STRING"/>
<log level="custom">
<property name="Step" value="Registry Path Resolved"/>
<property expression="get-property('registryPath')" name="RegistryPath"/>
</log>
<property expression="json-eval($.value)" name="valueToWrite" scope="default" type="STRING"/>
<log level="custom">
<property name="Step" value="Value extracted from payload"/>
<property expression="get-property('valueToWrite')" name="ValueToWrite"/>
</log>
<class name="org.wso2.custom.mediators.RegistryWriteHandlerMediator"/>
<log level="custom">
<property name="Step" value="Post Custom Mediator Write"/>
<property expression="get-property('registryPath')" name="RegistryPath"/>
<property expression="get-property('valueToWrite')" name="ValueWritten"/>
</log>
<payloadFactory media-type="json">
<format>
{
"status": "success",
"message": "Value written successfully",
"details": {
"namespace": "$1",
"key": "$2",
"value": "$3",
"path": "$4"
}
}
</format>
<args>
<arg evaluator="xml" expression="get-property('uri.var.namespace')"/>
<arg evaluator="xml" expression="get-property('uri.var.key')"/>
<arg evaluator="xml" expression="get-property('valueToWrite')"/>
<arg evaluator="xml" expression="get-property('registryPath')"/>
</args>
</payloadFactory>
<property name="messageType" scope="axis2" type="STRING" value="application/json"/>
<respond/>
</inSequence>
<outSequence>
<log level="custom">
<property name="Step" value="Exiting RegistryWriteAPI"/>
</log>
</outSequence>
<faultSequence>
<log level="full">
<property name="Step" value="Fault Occurred"/>
<property expression="get-property('ERROR_MESSAGE')" name="ERROR_MESSAGE"/>
<property expression="get-property('ERROR_CODE')" name="ERROR_CODE"/>
</log>
<payloadFactory media-type="json">
<format>
{
"status": "error",
"message": "An error occurred while processing the request",
"details": {
"error_message": "$1",
"error_code": "$2"
}
}
</format>
<args>
<arg evaluator="xml" expression="get-property('ERROR_MESSAGE')"/>
<arg evaluator="xml" expression="get-property('ERROR_CODE')"/>
</args>
</payloadFactory>
<property name="messageType" scope="axis2" type="STRING" value="application/json"/>
<respond/>
</faultSequence>
</resource>
</api>