1

Hello I am working on a CSV file using camel bindy component where I split data into 1000 line of chunks and its generating header columns with each chunks, I need it should generate only one time with single file. MyRoute:

final DataFormat inputCSV = new BindyCsvDataFormat(InputCSV.class);
final DataFormat outputCSV = new BindyCsvDataFormat(OutputCSV.class);

@Override
public void configure() throws Exception {
    from("file:inbox/inputFile?fileName=inputProducts.csv&noop=true")
        .split().tokenize("\\n", 1000)
        .unmarshal(inputCSV)
        .bean(Processor.class, "processCSV")
        .marshal(outputCSV)
        .to("file:inbox/outputFile?fileExist=append&fileName=outputProduct.csv");
}

And my OutputCSV.java pojo

@CsvRecord(separator = ",",generateHeaderColumns=true)
public class OutputCSV implements Serializable {

private static final long serialVersionUID = 1L;

@DataField(pos = 1, required = true)
private String product_id;

@DataField(pos = 2, required = true)
private String product_name;

//Getter and setter
}

My question is how do I make this code so it will generate header once for single file ?

Rajat.r2
  • 137
  • 2
  • 13

1 Answers1

2

You get a header per row because you process every single line and append to the file. In such a scenario you would have to set the generateHeaderColumns to false after the first line because only the file knows if the current row is the first one or not.

Either

  1. You collect (aggregate) the whole data for a file before you marshal it (see below)
  2. OR you add the header "manually" at the beginning of the file and set generateHeaderColumns to false
  3. OR you don't split the file at all to get a List of objects from the unmarshal (see below)

For #1 you would have to implement an AggregationStrategy that collects all objects in a List. See here and look for ArrayListAggregationStrategy.java for an example.

For #3 the result of the unmarshal is a List of Maps where each Map contains the model objects from 1 CSV row (in your case it should be only 1 object per Map). Then your bean can iterate over the List (instead of working on one row), extract the model objects and collect them in a List to marshal them again. See the Camel Bindy docs under the section Unmarshaling for more details.

burki
  • 6,741
  • 1
  • 15
  • 31
  • I did aggregation but I am doing wrong please can you show me how I use aggregate in DSL to collect all chunks and marshal together. – Rajat.r2 Mar 07 '18 at 11:28
  • I have extended my answer with a third variation and some more details – burki Mar 07 '18 at 13:33