Cette solution a été réalisée sur un BizTalk Server 2013 R2 et nécessite l’installation des adapteurs NSoftware v4.
Plus d’informations : https://www.nsoftware.com/adapters/biztalk/
Dans le cadre d’un projet récent, nous avons rencontré une problématique inhabituelle chez un client.
En voici le bref exposé :
Le partenaire de ce dernier (que nous appellerons ici « Y ») fournit à notre client (ici « X ») une liste de fichiers à heure régulière via un emplacement FTP.
La principale problématique réside dans le fait que X doit, par rapport à l’ensemble des fichiers présents sur le FTP à un instant T, récupérer l’ensemble des fichiers ET les intégrer dans une base de données Oracle dans un ordre bien précis. Ici, l’ordonnancement des messages se fait sur une date fonctionnelle contenue dans le corps du message lui-même.
A priori (et dans un monde idéal !), ce genre de scénario devrait être géré en amont :par exemple en envoyant les messages déjà dans l’ordre et via un protocole en mesure de garantir l’ordre (ex : Microsoft ServiceBus, MSMQ, IBM MQSeries…).
Mais grâce à l’adapteur FTP fourni par NSoftware (https://www.nsoftware.com/adapters/biztalk/), ce scénario peut tout à fait être géré avec BizTalk.
En voici le détail :
Nous allons ici exploiter une fonctionnalité assez méconnue de l’adapteur FTP NSoftware : l’option « DownloadSingleFile » (propriété « Other settings » de l’adapter).
Je vous invite à parcourir la documentation de l’adapteur (celle-ci est plutôt bien fournie et souvent accompagnée d’exemples) : https://cdn.nsoftware.com/help/EAB/bt/FTPConfig.htm
Comme le dit très bien la documentation, cette option, utilisée sur un port d’envoi, permet de télécharger un fichier plutôt que l’uploader.
Ce qui est inhabituel est d’utiliser un port d’envoi pour réceptionner des messages et non un port de réception.
Pour cela, le port d’envoi doit être utilisé en « solicit-response ».
Nous utiliserons d’abord un DIR qui va retourner la liste des fichiers présents sur le FTP puis une boucle qui récupèrera les fichiers 1 par 1.
Voici les étapes de notre flux :
Nous sommes dans une situation où nous devons planifier le déclenchement du processus de récupération des fichiers.
Voici comment, dans notre cas, nous gérons cette planification avec le « Task Scheduler Windows ».
Il existe plusieurs façons de déclencher une orchestration mais dans notre cas, l’orchestration s’activera de la manière suivante :
Code exemple :
set FilePath=D:\Data\EAI\…\Scheduler
echo ^<Trigger xmlns^= »https://Monnamespace.Trigger »^> ^<Value^>1^</Value^> ^</Trigger^>>%FilePath%\triggerOrc.xml
Note : il serait tout à fait possible d’utiliser ici l’adapteur ScheduleTask. Plus d’infos : https://biztalkscheduledtask.codeplex.com/
*Début de l’orchestration :
intFilesNumber = xpath(msgDirResponse, »count(Directory/File) »);
*Configuration du port d’envoi :
Comme dit précédemment, l’adapteur du port d’envoi doit être nsoftware.FTP v4. Pas de configuration particulière pour les 2 pipelines (PassThru), pas de maps, pas de filtres (car lié à l’orchestration).
Ci-dessous la configuration de l’adapteur :
L’élément le plus important ici est bien sûr : ListDirectory=true à mettre dans « Other ». Cette propriété permet d’indiquer à l’adapter que nous voulons déclencher un « DIR » dans le répertoire FTP distant. L’adapter sait qu’il doit nous retourner non pas des fichiers mais une liste des fichiers présents dans le répertoire.
*Boucle pour récupérer les messages 1 par 1 :
– Suite de l’orchestration
Remarque : ce n’est pas nécessaire dans notre cas mais on pourrait tout à fait « stamper » les messages du même lot en créant une propriété promue custom qui contiendrait le numéro du lot par exemple. Tout comme le fait l’InterchangeId lors d’un débatching.
– Configuration du port d’envoi
Même principe que pour le précédent port d’envoi, l’adapteur de celui-ci doit être nsoftware.FTP v4. Pas de configuration particulière pour les 2 pipelines (PassThru pour le pipeline d’envoi et XMLReceive en réception), pas de maps, pas de filtres (car lié l’orchestration).
Ci-dessous la configuration de l’adapteur :
Comme tout à l’heure, l’élément le plus important ici est dans « Other » :
DownloadSingleFile=true
DeleteAfterDownload=true
La propriété DownloadSingleFile=true indique à l’adapter que l’on souhaite récupérer un fichier dont le nom est précisé dans la propriété de contexte
nsoftware.BizTalk.FTP.RemoteFile.
La propriété DeleteAfterDownload=true indique que l’on souhaite supprimer le fichier après l’avoir téléchargé.
*Facultatif : traitement spécifique à notre problématique
– Trier les messages
Pour rappel, le client impose l’intégration des messages du lot récupéré dans un ordre bien précis (basé sur une date fonctionnelle contenue dans le message).
Pour faire cela, nous utilisons simplement une map avec comme message source, notre msgListeItemsTemp et en message destination un msgListeItemsOrdered, tous les 2 de type ListeItems.
Cette map réalisée en full xslt ressemble à quelque chose comme cela :
<s0:ListeItemsEnvelope>
<xsl:for-each select=« s0:Item« >
<xsl:sort select=« MyFunctionalDate data-type=« number » order=« ascending« />
<xsl:element name=« s0:Item« >
<xsl:copy-of select=« ./*« />
</xsl:element>
</xsl:for-each>
</s0:ListeItemsEnvelope>
– Débatcher les messages
Ici, le choix a été fait de débatcher les messages en appelant un pipeline directement dans l’orchestration.
Sachant qu’il est toujours préférable de débatcher un message via un pipeline qui est appelé directement dans l’orchestration.
Voici tout de même la capture d’écran :
On obtient ainsi à la fin de la shape Construct message un message unitaire de type Item.
*Traitement spécifique et envoi des messages 1 par 1 :
A partir de là, nous sommes libres d’effectuer n’importe quel traitement / transformation sur notre message Item.
Dans notre cas, comme vous pouvez le constater sur la capture d’écran ci-dessous, nous allons simplement appliquer une map (2) selon un certain statut (1) récupéré au préalable.
Puis, comme nous sommes toujours dans la boucle qui débatche notre message de type msgListeItems, nous allons envoyer les messages 1 par 1 (3) sur un port d’envoi (4). Dans notre cas, le binding est en « Specify later » et le port d’envoi physique de type WCF-OracleDB.
Avec cette solution, nous pouvons donc garantir à notre client qu’au moment où l’orchestration va se déclencher, tous les fichiers présents sur l’emplacement FTP seront listés, pris ensemble et traités par la suite de la façon de notre choix.