Search code examples
jsoncsvapache-camel

Converting CSV file to JSON and send it to a JMS queue


My aim is to read a CSV file, convert it to JSON, and send the generated JSON one by one to a JMS queue. My Code below:

final BindyCsvDataFormat bindy=new BindyCsvDataFormat(camelproject.EquityFeeds.class);
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616");
CamelContext _ctx = new DefaultCamelContext(); 
_ctx.addComponent("jms", JmsComponent.jmsComponentAutoAcknowledge(connectionFactory));
_ctx.addRoutes(new RouteBuilder() {
    
    public void configure() throws Exception {
        from("file:src/main/resources?fileName=data-sample.csv")
        .unmarshal(bindy)
        .marshal()
        .json(JsonLibrary.Jackson).log("${body}")
        .to("file:src/main/resources/?fileName=emp.json");
    }
    
});

EquityFeeds is my POJO class in the above code.

Issues:

  1. No Output is produced. "emp.json" file does not get generated at the given location.
  2. Also how do I split the generated JSON into individual JSON's and send it to a JMS queue like what I did for XML as below:
.split(body().tokenizeXML("equityFeeds", null)).streaming().to("jms:queue:xml.upstream.queue");

EquityFeeds (POJO):

@CsvRecord(separator = ",",skipFirstLine = true)
public class EquityFeeds {
        
    @DataField(pos = 1) 
    private String externalTransactionId;

    @DataField(pos = 2)
    private String clientId;

    @DataField(pos = 3)
    private String securityId;

    @DataField(pos = 4)
    private String transactionType;

    @DataField(pos = 5)
    private Date transactionDate;

    @DataField(pos = 6)
    private float marketValue; 

    @DataField(pos = 7)
    private String priorityFlag;
    
    // getters and setters... 
}

Please Note: I commented the .marshal() and .json() to check if the .unmarshal() is working but the unmarshal is also not working as "emp.json" is not getting created.


Solution

  • If nothing happens at all when starting the route then it is most likely due to the relative path you passed to the file component. Probably the execution directory of your Java process is not where you think it is and the file is not found. To simplify things I suggest you start with an absolute path. Once everything else is working figure out the correct relative path (your base should be the value of the user.dir system property).

    Re your question about splitting the contents: This is answered in the documentation.

    This works for me (Camel 3.1):

    public class CsvRouteBuilder extends EndpointRouteBuilder {
        @Override
        public void configure() {
            DataFormat bindy = new BindyCsvDataFormat(BindyModel.class);
    
            from(file("/tmp?fileName=simpsons.csv"))
                .unmarshal(bindy)
                .split(body())
                .log("Unmarshalled model: ${body}")
                .marshal().json()
                .log("Marshalled to JSON: ${body}")
                // Unique file name for the JSON output
                .setHeader(Exchange.FILE_NAME, () -> UUID.randomUUID().toString() + ".json")
                .to(file("/tmp"));
        }
    }
    
    // Use lombok to generate all the boilerplate stuff
    @ToString
    @Getter
    @Setter
    @NoArgsConstructor
    // Bindy record definition
    @CsvRecord(separator = ";", skipFirstLine = true, crlf = "UNIX")
    public static class BindyModel {
    
        @DataField(pos = 1)
        private String firstName;
        @DataField(pos = 2)
        private String middleName;
        @DataField(pos = 3)
        private String lastName;
    
    }
    

    Given this input in /tmp/simpsons.csv

    firstname;middlename;lastname
    Homer;Jay;Simpson
    Marge;Jacqueline;Simpson
    

    the log output looks like this

    Unmarshalled model: RestRouteBuilder.BindyModel(firstName=Homer, middleName=Jay, lastName=Simpson)
    Marshalled to JSON: {"firstName":"Homer","middleName":"Jay","lastName":"Simpson"}
    Unmarshalled model: RestRouteBuilder.BindyModel(firstName=Marge, middleName=Jacqueline, lastName=Simpson)
    Marshalled to JSON: {"firstName":"Marge","middleName":"Jacqueline","lastName":"Simpson"}
    

    and two json files are written in /tmp.