Dans cet article, je vous montrerai comment transformer des données venant d’un CSV au format XML grâce à l’outil Talend ESB et son framework Camel, chaque lignes du fichier devenant un fichier XML différent.
Suite à ce poste sur developpez.com et la découverte de ce dépot github, j’ai voulu traduire ce besoin avec Talend ESB et la perspective médiation.
Le but est de convertir un fichier CSV en fichier XML grâce à deux composants Camel de type format, le premier étant bindy pour la partie CSV s’appuyant sur la librairie Apache Commons CSV et le deuxième jaxb pour la partie XML, mon second objectif est de n’écrire aucune ligne de code java grâce à Talend, les seules lignes de code nécessaires en dehors de Talend seront générées automatiquement.
Ces deux composants se marient assez bien puisqu’ils utilisent tous les deux des annotations java permettant de transformer des fichiers en objets java (POJO), cette action se nomme ‘unmarshalling’, l’inverse étant le ‘marshalling’.
Pour commencer
Sachez que le projet Talend à importer ainsi que le CSV d’exemple sont disponibles sur mon dépôt GitHub 😉
Les classes java seront générées grâce à l’outil xjc dont vous trouverez plus d’explications ici, l’outil xjc est fournis dans le répertoire bin de votre JDK préférée. Si vous n’êtes pas très à l’aise avec le xml et que vous ne possédez pas d’outil d’édition, vous pouvez générer un xsd depuis un fichier xml avec trang mais ce n’est pas le sujet du jour 😉
Lancez la commande suivante:
Les deux fichiers générés sont les classes Customer.java et ObjectFactory.java, le premier est le fameux POJO correspondant aux clients et le deuxième est une classe de génération d’instances d’objets.
Créer une route dans Talend
Créer deux beans ObjectFatory et Customer et copier coller ensuite le code généré par xjc, vous remarquerez que le nom du package correspond déjà à celui qu’utilise Talend ESB, à savoir ‘beans‘. Il faut simplement ajouter les annotations spécifiques à bindy afin de définir les positions des champs dans le CSV ainsi que le bon séparateur (généralement virgule ou point virgule).
Ajouter les composants suivants:
- Deux CFile
- Deux CMessageEndPoint
- Un CSplitter
Composant CFile de lecture
Rien de particulier avec ce composant, spécifiez le nom du CSV à lire.
Composant CMessageEndPoint pour bindy
Ce composant doit être paramétré pour appeler le composant de transformation dataformat, on appelle ici la méthode unmarshal (fichier vers objet java), on précise la classe java.
N’oubliez pas de sélectionner bindy dans les paramètres avancés pour ajouter les dépendances.
Composant CSplitter
On splitte le body qui va être une liste d’objets java à savoir List<beans.Customer>
Composant CMessageEndPoint pour Jaxb
Appel du composant de transformation dataformat mais cette fois pour faire du marshalling (objet vers fichier).
N’oubliez pas de sélectionner jaxb dans les paramètres avancés pour ajouter les dépendances.
Composant CFile d’écriture
Petite astuce: Utilisez la propriété CamelSplitIndex pour générer vos noms de fichiers, c’est une variable de header générée par le splitter
Lancement du job
Les 3 lignes de CSV vont donc générer 3 fichiers XML, il est bien sûr possible de générer un seul XML pour plusieurs lignes de CSV mais je vous invite à lire la documentation de camel-bindy et l’annotation @OneToMany.
Conclusion
Voici une manière élégante, simple et efficace de générer des XML à la volée grâce à la puissance des composants Camel en mode convention plutôt que configuration 😉
I am trying to use this and it doesn’t work. I cloned from the GIT repository.
I created a cConfig and added « camel-bindy » jar to the Dependecny lib path.
Also, when I look in the Bean, it looks like it cant find « commons » or « dataformat » imports
I am new to Talend, I am not sure what I need to do.
RouteId ProcessorId Processor Elapsed (ms)
[CsvToXml_cFile_1 ] [CsvToXml_cFile_1 ] [file:///tmp/data?autoCreate=false&bufferSize=128&fileName=data.csv&flatten=fal] [ 1]
[CsvToXml_cFile_1 ] [CsvToXml_cMessagin] [dataformat:bindy-csv:unmarshal?classType=beans.Entity ] [ 1]
Stacktrace
—————————————————————————————————————————————
java.lang.IllegalArgumentException: The separator has not been defined in the annotation @CsvRecord or not instantiated during initModel. must be specified
Hello,
The error message come from the bindy dataformat (see http://camel.apache.org/bindy.html).
The separator is mandatory and defined in the pojo « Entity » -> @CsvRecord(separator = « , »), you can also add &separator=\ »;\ » in the cMessagingEndpoint dsl.