Apache Camel (second volet) : transformation des données d'un fichier texte Utilisation du format Bindy

Il est possible d'améliorer cette solution pour obtenir directement la conversion d'une ligne en un objet. Dans le cas d'un fichier CSV, cela passe par l'utilisation du format de données Bindy. Après l'inclusion de l'artefact camel-bindy dans le classpath, il faut écrire un bean POJO correspondant aux colonnes. La liaison entre les données et les objets est spécifiée avec des annotations :


 package org.netapsys.csv.descripteur;

import org.apache.camel.dataformat.bindy.annotation.CsvRecord;
import org.apache.camel.dataformat.bindy.annotation.DataField;

@CsvRecord(separator = ",", crlf = "UNIX")
public class Descripteur
{
   @DataField(pos = 1)
   private String nom = "";

   @DataField(pos = 2)
   private String zone = "";

   @DataField(pos = 3, pattern = "yyyy-MM-dd")
   private Date date = null;

   @DataField(pos = 4,required = false)
   private String titulaire = "";

   // Omission des accesseurs .../...

   // Juste pour faciliter la lecture des traces.
   @Override
   public String toString()
   {
       return "Descripteur [nom=" + getNom() + ", zone=" + getZone() + ", date=" + getDate()
               + ", titulaire=" + getTitulaire() + "]";
   }
}


Reste ensuite à modifier la route, pour demander la conversion :

from("file:/tmp/csv?noop=true&fileName=test.csv")
.split(body().tokenize("\n"))
.log("ligne: $")
.unmarshal().bindy(BindyType.Csv, "org.netapsys.csv.descripteur")
.bean(ImportBindy.class).end();


On utilise un autre bean pour traiter chaque objet car le format Bindy retourne une liste de dictionnaires d'objets :

 public class ImportBindy
{
   Logger log = LoggerFactory.getLogger(ImportBindy.class);

   public void importer(final List<HashMap<String, Descripteur>> donnees)
   {
       for (final HashMap<String,Descripteur> dictionnaire : donnees) {
           for (final String cle : dictionnaire.keySet()) {
                   this.log.info("toString: " + dictionnaire.get(cle));
           }
       }
   }
}


La trace d'exécution permet de vérifier que c'est bien la méthode toString() de la classe Descripteur qui est finalement appelée :

55,250 INFO route1(212): ligne: nomdomaine,fr,2013-10-11,OWN-4413-4431
55,251 DEBUG BindyCsvDataFormat(178): Size of the record splitted : 4
55,251 DEBUG BindyCsvFactory(177): Pos : 1, Data : nomdomaine, Field type : class java.lang.String
55,251 DEBUG BindyCsvFactory(177): Pos : 2, Data : fr, Field type : class java.lang.String
55,252 DEBUG BindyCsvFactory(177): Pos : 3, Data : 2013-10-11, Field type : class java.util.Date
55,252 DEBUG BindyCsvFactory(177): Pos : 4, Data : OWN-4413-4431, Field type : class java.lang.String
55,252 DEBUG BindyCsvFactory(213): Counter mandatory fields : 0
55,252
DEBUG BindyCsvDataFormat(191): Graph of objects created :
{org.netapsys.csv.descripteur.Descripteur=Descripteur [nom=nomdomaine,
zone=fr, date=Fri Oct 11 00:00:00 CEST 2013, titulaire=OWN-4413-4431]}
55,253 
INFO ImportBindy(30): toString: Descripteur [nom=nomdomaine, zone=fr,
date=Fri Oct 11 00:00:00 CEST 2013, titulaire=OWN-4413-4431]