1
votes

I am creating zip files in Camel using the ZipAggregationStrategy and need to set the output filename based on a custom property set in an invoking exchange. However, the exchange that I receive after my zip aggregation contains none of my properties.

My general flow is:

  1. Processor which sets custom properties on the exchange (dynamic, based off database query)
  2. Bean which produces List of zip file contents
  3. Camel aggregator using ZipAggregationStrategy, based off the example in the Camel documentation.

After step 3., I wish to dynamically name the zip based off properties I set on the exchange in step 1., but the exchange only contains Camel properties (CamelFileExchangeFile with the path to the zip file, etc.) because a new exchange is being created in aggregate():

@Override
public Exchange aggregate(Exchange oldExchange, Exchange newExchange) {
    File zipFile;
    Exchange answer = oldExchange;

    // ...

    DefaultEndpoint endpoint = (DefaultEndpoint) newExchange.getFromEndpoint();
    answer = endpoint.createExchange();
    answer.addOnCompletion(new DeleteZipFileOnCompletion(zipFile));

    // ...

    genericFile.bindToExchange(answer);  

    // ...

    return answer;
}
1
Camel doesn't suppose to copy the properties in default aggregater, as it is hard to tell which property need to be copy if the exchanges use different properties. If you want to set the FILE_NAME, you can just put the custom process jut before the setHeader DSL. - Willem Jiang
The problem with this is that in my situation, the custom process can only be executed prior to the aggregation taking place. The filename needs to be dynamic, and after aggregation there is currently no means to generate this. Peter's approach is the only way that currently works, but it's a bit of a kludge. - nullPainter

1 Answers

2
votes

I guess this is a bug. The properties should be preserved and not be removed by the aggregation strategy. I opened a Jira issue in the hope that this will be fixed: CAMEL-7555.

As as workaround extend ZipAggregationStrategy and override aggregate:

public class MyZipAggregationStrategy extends ZipAggregationStrategy {
    @Override
    public Exchange aggregate(final Exchange oldExchange, final Exchange newExchange) {
        final Exchange answer = super.aggregate(oldExchange, newExchange);
        answer.setProperty("myZipName", newExchange.getProperty("myZipName")); // Hack!!
        return answer;
    }
}

Use MyZipAggregationStrategy as follows:

public class MyRouteBuilder extends RouteBuilder {
    @Override
    public void configure() {
        from("file:zipper/in?include=.*.xml&noop=true")
            .process(new Processor() {
                @Override
                public void process(final Exchange exchange) throws Exception {
                    exchange.setProperty("myZipName", "messages.zip");
                }
            })
            .aggregate(new MyZipAggregationStrategy())
            .constant(true)
            .completionFromBatchConsumer()
            .eagerCheckCompletion()
            .setHeader(Exchange.FILE_NAME, simple("${property.myZipName}")) // setting ZIP file name
            .to("file:zipper/out");
    }
}