Dans un projet Biztalk, il existe plusieurs moyens de modifier ou transformer des messages XML. Ceux-ci peuvent dépendre de l’élément dans lequel le traitement est réalisé (orchestration, map ou pipeline). Il est possible d’opérer les modifications grâce à :
Nous avons fait le choix de traiter la modification de messages XML dans une orchestration à l’aide de méthodes (que l’on appellera helpers) d’une bibliothèque externe. L’approche proposée est cependant utilisable au sein d’un pipeline ou d’une map.
Cet article est organisé autour des deux axes suivants :
Afin d’inscrire cette approche dans un exemple concret, nous proposons la mise en place d’une application Biztalk simple. Pour cela, nous créons un projet Biztalk nommé BlogProject_XSDTool au sein d’une solution BlogProject.
Dans ce projet, nous construisons un schéma ProductList contenant des éléments Product (nœud répétable).
Nous ajoutons également une orchestration composée d’un port logique de réception (pour des messages ProductList), un bloc Assignment (qui ne fait qu’affecter le message d’entrée au message de sortie) et un port logique d’envoi (pour des messages ProductList)
Ce projet est déployé au sein d’une application Biztalk dans laquelle les ports d’entrée et de sortie de l’orchestration sont respectivement liés à un emplacement de réception (via un port de réception) et à un port d’envoi, tous deux de type FILE.
Cette construction permet donc de déposer un fichier XML de type ProductList dans un répertoire et de récupérer le message en sortie sous la forme d’un fichier de type ProductList dans un autre répertoire.
Pour finir, nous créons un projet Bibliothèque de classes BlogProject_Helpers dans la solution BlogProject et l’ajoutons comme référence du projet Biztalk. C’est dans ce projet que nous allons mettre en place la modification des messages XML.
Le but est de transformer un message XML en objet C# pour pouvoir le manipuler à l’aide du Framework .Net. Pour cela, nous allons utiliser l’ outil XML Schema Definition (xsd.exe) qui est fourni avec Visual Studio et est apparu avec la version 2.0 du Framework .Net.
Cet utilitaire permet de générer des schémas XML ou des classe C# à partir de fichiers XDR, XML et XSD ou de classes C# (comme nous le montre la documentation). La fonctionnalité qui nous intéresse ici est la génération d’une classe C# à partir d’un schéma XML (.xsd).
Pour réaliser cette opération, il faut ouvrir le Developer Command Prompt de Visual Studio est taper la commande suivante :
xsd.exe {chemin_vers_le_schéma}\ProductList.xsd /c /o:{chemin_vers_le_dossier_de_la_classe}
Il faut spécifier le chemin vers notre fichier XSD à la place de {chemin_vers_le_schema} et le chemin vers le dossier dans lequel nous voulons déposer la classe générée à la place de {chemin_vers_le_dossier_de_la_classe} (dans notre cas, dans le dossier du projet BlogProject_Helpers).
Une fois la commande exécutée, un fichier ProductList.cs apparait dans le dossier choisi. Voici un aperçu :
Pour utiliser la classe nouvellement générée, nous créons une classe ProductListBuilder. Cette classe va nous permettre, dans un premier temps, de construire une instance C# de ProductList à partir d’un XLANGMessage (documentation) venant de notre orchestration et, après modification éventuelle, de convertir cette instance en XLANGMessage pour l’orchestration.
Le type CustomBTXMessage, à ajouter dans le projet BlogProject_Helpers, permet de réaliser la conversion entre l’instance d’un objet sérialisable et un XLANGMessage, grâce à son héritage de BTXMessage (documentation).
Après compilation, il est possible de réaliser cet appel dans le bloc Assignment de l’orchestration :
Evidemment, pour le moment, cela ne fait rien de plus que la simple affectation de la partie Mise en place. Mais nous pouvons déjà voir les avantages et les inconvénients de cette approche.
Ce qui ressort des parties précédentes est que l’approche présentée n’a pas vraiment d’intérêt pour des transformations ciblées ou simples que l’on pourra réaliser plus facilement avec XPath ou une map, par exemple. Cependant, certaines transformations complexes justifient parfaitement l’utilité d’un helper.
L’exemple que nous avons choisi de mettre en œuvre est le suivant. Un produit possède un identifiant, un nom, une couleur et une quantité. Nous voulons cumuler les quantités, et donc fusionner les éléments Product, mais seulement quand l’identifiant, le nom et la couleur sont les mêmes. Dans le cas contraire, il faut bien garder deux éléments distincts.
Grâce à la modélisation de notre message sous forme d’objet C#, il est possible d’utiliser des outils comme LINQ To XML. Le problème se résout alors en modifiant la classe ProductListBuilder de la manière suivante :
La requête LINQ (en vert) transforme d’abord chaque produit en une instance de type anonyme {Id, Name, Quantity, Color} pour le manipuler plus facilement. Ensuite elle groupe ces instances grâce à la clé {Id, Name, Color}, en spécifiant qu’il faut cumuler les quantités des éléments fusionnés.
Une liste de ProductListProduct est alors construite avec linqProducts et affectée à la propriété Product de l’instance de type ProductList à renvoyer.
Cette méthode est appelée dans NewProductList() à la place de ConstructProductList(). Il n’est donc pas nécessaire de modifier l’orchestration (encore un avantage !).
Si l’on déploie le projet Biztalk et ses dépendances dans l’application Biztalk, le fichier entrant (à gauche) est bien transformé, comme souhaité, en sortie (à droite).
L’approche décrite dans cet article ne s’applique idéalement qu’à certaines situations car en raison des surcoûts engendrés (développement et temps d’exécution), s’il est possible de faire sans, il vaut mieux éviter. Mais si des traitements complexes (comme dans notre exemple) sont nécessaires, c’est une solution propre et relativement directe qui permet de résoudre le problème aussi bien dans une orchestration, dans une map ou dans un pipeline.