On s'intéresse ici au composant 'camel-bindy' qui permet de transformer des données non structurées (csv par exemple) en objets java et inversement.
La démo est réalisée en quatre actes: configurer le pom du projet, dessiner et déclarer la route, annoter le bean du model et enfin tester.
la v2.10.2 de camel-bindy est utilisée.
Voici les détails de la démo.
La démo du composant bindy est un projet maven réalisé en quatre actes:
ACTE1. Configurer le pom
<dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-bindy</artifactId> <version>2.10.2</version> </dependency>
ACTE2. Dessiner la route et la déclarer dans spring
package fr.netapsys.camel.routes; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.dataformat.bindy.csv.BindyCsvDataFormat; public class BindyRoute extends RouteBuilder { @Override public void configure() throws Exception { from("file://src/?noop=true&fileName=persons.csv") .unmarshal(new BindyCsvDataFormat("fr.netapsys.camel.beans")) .to("mock:results.csv") .end(); } }
La route pointe sur un fichier persons.csv localisé dans src.
La méthode unmarshall se charge de convertir les données en csv via l'argument BindyCsvDataFormat.
BindyCsvDataFormat prend en argument les noms des packages des classes annotées.
Elle prend aussi comme argument la classe annotée (voir la javadoc).
N'oublier pas d'ajouter dans le fichier camel-context.xml une référence sur BindyRoute comme suit:
<camel:camelContext xmlns="http://camel.apache.org/schema/spring"> <camel:routeBuilder ref="bindyRoute" /> </camel:camelContext>
Le principe de "Convention over configuration" attend que le fichier camel-context.xml dans src/META-INF/spring.
ACTE3. Annoter le bean du model pour camel-bindy
package fr.netapsys.camel.beans; import java.io.Serializable; import org.apache.camel.dataformat.bindy.annotation.CsvRecord; import org.apache.camel.dataformat.bindy.annotation.DataField; @CsvRecord(separator = ",", skipFirstLine=true) public class Personne implements Serializable { @DataField(pos = 1) private String nom; @DataField(pos = 2) private String prenom; @DataField(pos = 3) private String age; public Personne(){} public Personne(String nom,String prenom,String age){ setNom(nom); setPrenom(prenom); setAge(age); } //... getters / setters toString omis... }
Explications:
L'annotation @CsvRecord de org.apache.camel.dataformat.bindy précise que ce bean servira à la transformation csv.
Les deux attributs de cette annotation permettent de définir le séparateur et d'ignorer la première ligne.
Le reste des annotations de bindy servent à structurer les données.
Attention, pensez à écrire le constructeur par défaut si vous en créez un ou plusieurs avec arguments.
ACTE4. Tester
Vérifions que, dans le répertoire src/, l'existence d'un fichier persons.csv contenant les lignes à transformer en objets java.
Ces lignes doivent avoir trois colonnes nom, prénom et age comme suit:
[persons.csv] nom,prenom,age Toto,To,30 Titi,Ti,32 ......
Voici le code du test:
package fr.netapsys.camel.tests; import java.util.*; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.mock.MockEndpoint; import org.apache.camel.test.junit4.CamelTestSupport; import org.junit.*; import fr.netapsys.camel.beans.Personne; import fr.netapsys.camel.routes.BindyRoute; public class BindyRouteTest extends CamelTestSupport { final String clazzModel="fr.netapsys.camel.beans.Personne"; @Override protected RouteBuilder createRouteBuilder() throws Exception { return new BindyRoute(); } @Test public void testBindyCamel() throws Exception { MockEndpoint mock = getMockEndpoint("mock:results.csv"); mock.expectedMessageCount(1); assertMockEndpointsSatisfied(); List<Map<String, Personne>> listMapPersons = (List<Map<String, Personne>>) mock .getReceivedExchanges().get(0).getIn().getBody(); Assert.assertTrue(listMapPersons.size()==2); Assert.assertTrue(listMapPersons.get(0) .get("fr.netapsys.camel.beans.Personne")!=null); } }
Les lignes du fichier persons.csv sont transformées en liste d'instances Personne.
Voilà tout!