Michael Hoffman
Michael Hoffman

Reputation: 454

Camel CSV Component Not Outputting Headers Correctly

I have the following 2.14.1 route:

           from("activemq:queue:ABC_FULFILLMENT_REQUEST")
                 .aggregate(new ABCFulfillmentCenterAggregationStrategy())
                 .xpath(
                       "/o:Order/o:OrderType/o:FulfillmentCenter = '"
                             + com.pluralsight.orderfulfillment.generated.FulfillmentCenter.FULFILLMENT_CENTER_ONE.value()
                             + "'", Boolean.class, namespace)
                 .completionInterval(10000)
                 .beanRef("aBCFulfillmentProcessor", "processAggregate").marshal()
                 .csv().to("file://" + filePath).to("mock:direct:result");

My aggregation strategy correlates XML where the fulfillmentcenter element's text is of a certain value. This works correctly. My message translator then takes the exchange and processes it:

   public List<Map<String, Object>> processAggregate(List orders) throws Exception {
  log.info("Processing the aggregate");
  List<Map<String, Object>> results = new ArrayList<Map<String, Object>>();

  // 1 - Add the header first
  Map<String, Object> header = new HashMap<String, Object>();
  header.put("orderNumber", "Order Number");
  header.put("firstName", "First Name");
  header.put("lastName", "Last Name");
  results.add(header);

  try {
     if (orders != null) {
        // 2 - Add each order ID
        for (int i = 0; i < orders.size(); i++) {
           com.pluralsight.orderfulfillment.generated.Order order = unmarshallOrder((String) orders
                 .get(i));
           Map<String, Object> row = new HashMap<String, Object>();
           row.put("orderNumber", order.getOrderType().getOrderNumber());
           row.put("firstName", order.getOrderType().getFirstName());
           row.put("lastname", order.getOrderType().getLastName());
           results.add(row);
        }
     }
  } catch (Exception e) {
     log.error(
           "An error occurred while trying to process messages for the abc fulfillment center: "
                 + e.getMessage(), e);
     throw e;
  }
  return results;
}

As you can see, I'm accepting the list of orders as the parameter from the body of the exchange. First, I add a header to the list of maps I plan to return. I then unmarshal each XML from the input list and build maps to add to the return list.

Once message processing is complete, I marshall the results into CSV and then send the contents to a file.

The content that results in the body below is:

Last Name,Order Number,First Name ,1003,Jane,Smith ,1004,Larry,Horse ,1005,Michael,Tester

I expected the header to be in the correct sequence; however, its not. Also, an extra comma is output to the left. Now, if I don't add the map for the header, I get the following:

1003,Smith,Jane 1004,Horse,Larry 1005,Tester,Michael

Here are my questions:

  1. Is marshalling the csv then sending the exchange to a file an accepted approach? Or should I be using some other component in between the csv and file components.

  2. How do I maintain the order of elements in a row. For instance, I want to make sure that the columns are order number, first name, last name; however, the map keys are not the way I would want to assure order. Any guidance would be appreciated.

Let me know if there is anything else I can provide. Thank you in advance for your help.

Upvotes: 1

Views: 904

Answers (1)

Sergey
Sergey

Reputation: 1361

To maintain the order of elements in the row use LinkedHashMap instead. For example:

Map<String, Object> header = new LinkedHashMap<String, Object>();

The rest of the route is OK, you will get expected results when you fix the map used (no extra commas, etc)

Upvotes: 2

Related Questions