Transforming CSV to Java Objects using Camel

This tutorial shows how to perform a simple transformation from CSV to Java objects with Camel using as destination a processor or a JMS Queue.

 

First of all, we will define a class mapping our CSV file.

package com.sample.model;

import java.io.Serializable;
import org.apache.camel.dataformat.bindy.annotation.CsvRecord;
import org.apache.camel.dataformat.bindy.annotation.DataField;

@CsvRecord(separator = ",")
public class User implements Serializable {
  @DataField(pos = 1)
  private String name;

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public String getSurname() {
    return surname;
  }

  public void setSurname(String surname) {
    this.surname = surname;
  }

  @DataField(pos = 2)
  private String surname;

  @Override
  public String toString() {
    return "User [name=" + name + ", surname=" + surname + "]";
  }
}

As you can see, this class is annotated with a @CsvRecord that defines the separator to be used in the CSV file, and the list of fields in the CSV file, with its position. Here is for example a single row CSV we will use:

john,smith

And now the Route Builder class:

import org.apache.camel.CamelContext;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.dataformat.bindy.csv.BindyCsvDataFormat;
import org.apache.camel.impl.DefaultCamelContext;
import org.apache.camel.spi.DataFormat;

public class Hello {
  public static void main(String args[]) throws Exception {
    CamelContext context = new DefaultCamelContext();
    final DataFormat bindy = new BindyCsvDataFormat("com.sample.model");
    context.addRoutes(
        new RouteBuilder() {
          public void configure() {
            from("file:C:camelin?noop=true").unmarshal(bindy).process(new SimpleProcessor());
          }
        });
    context.start();
    Thread.sleep(10000);
    context.stop();
  }
}

As you can see this class, scans for CSV files contained in the folder C:\Camel\In, unmarshalls them using the BindyCsvDataFormat and produces Java Objects of type com.sample.model.User to the SimpleProcessor. Here is a basic implementation for SimpleProcessor which merely prints out the com.sample.model.User:

import java.util.ArrayList;
import java.util.HashMap;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import com.sample.model.User;

public class SimpleProcessor implements Processor {
  public void process(Exchange exchange) throws Exception {
    ArrayList<HashMap<String, Object>> list = (ArrayList) exchange.getIn().getBody();
    for (HashMap<String, Object> map : list) {
      for (String key : map.keySet()) {
        System.out.println("key : " + key);
        User user = (User) map.get(key);
        System.out.println("value : " + user);
      }
    }
  }
}

The objects are collected by the processor as HashMap of key/values contained in an ArrayList.

Creating a JMS endpoint

Let’s write now a more complex implementation which used an ActiveMQ destination for our objects:

import javax.jms.ConnectionFactory;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.camel.CamelContext;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.jms.JmsComponent;
import org.apache.camel.dataformat.bindy.csv.BindyCsvDataFormat;
import org.apache.camel.impl.DefaultCamelContext;
import org.apache.camel.spi.DataFormat;

public class HelloJMS {
  public static void main(String args[]) throws Exception {
    CamelContext context = new DefaultCamelContext();
    final DataFormat bindy = new BindyCsvDataFormat("com.sample.model");
    ConnectionFactory connectionFactory =
        new ActiveMQConnectionFactory("admin", "admin", ActiveMQConnection.DEFAULT_BROKER_URL);
    context.addComponent("test-jms", JmsComponent.jmsComponentAutoAcknowledge(connectionFactory));
    context.addRoutes(
        new RouteBuilder() {
          public void configure() {
            from("file:C:camelin?noop=true")
                .unmarshal(bindy)
                .to("test-jms:queue:testMQDestination");
          }
        });
    context.start();
    Thread.sleep(10000);
    context.stop();
  }
}

This example relies on the default TCP broker URL for ActiveMQ (tcp://hostname:61616). Provided that the User class is available in ActiveMQ classpath (pack the classes in a JAR file and include them in the lib folder of ActiveMQ), you will be able to see the Object in the Message Details of ActiveMQ console:

camel csv tutorial enterprise integration