Apache Camel根据请求丰富了带有文件内容的消息

时间:2013-04-11 11:24:37

标签: java rest java-ee cxf apache-camel

我正在实现RESTful服务(使用CXFRS组件),它应返回某些请求的文件。每个文件都由其ID和扩展名提取,即restfulservice.com/path/file/1/pdf。添加的每个文件永远不会更改。提取后不应移动或删除文件,通常应同时访问它们。这是我的Camel背景的一部分:

from("direct:fetchFile")
    .process(fetchFileProcessor) // set file.id & file.extension
    .bean(fileService, "fetchFile(${header.file.id}, ${header.file.extension})") // set body to filename
    .setHeader("CamelFileName", simple("${body}"))
    .choice()
        .when(header("file.extension").isEqualTo("xml"))
            .pollEnrich("file:///{{application.fileStorage.basePath}}/xml?noop=true", 500)
        .when(header("file.extension").isEqualTo("pdf"))
            .pollEnrich("file:///{{application.fileStorage.basePath}}/pdf?noop=true", 500)
    .end()
    .convertBodyTo(File.class)
    .bean(responseProvider, "getResponse(${body}, 200)");

此配置的问题是响应只有第二个(为什么?)请求的非空主体,没有超时设置服务在第二个请求上使用调试消息进入永久循环

DEBUG o.a.c.c.f.FileConsumer - Took 0.000 seconds to poll <base path>\xml

Apace Camel版本为2.10.4

任何帮助将不胜感激

UPD1
Content Enricher页面上有警告,说'pollEnrich不访问当前Exchange的任何数据'。但是,如果我将fileName=${body}添加到文件网址

,则不会发生任何变化

UPD2
似乎pollEnrich不支持在URL(link)中指定的动态fileName。目前的路线:

from("direct:fetchFile")
    .process(fetchFileProcessor) // set file.id & file.extension
    .bean(fileService, "fetchFile(${header.file.id}, ${header.file.extension})") // set body to filename
    .choice()
        .when(header("file.extension").isEqualTo("xml"))
            .pollEnrich("file:///{{application.fileStorage.basePath}}/xml?fileName=${body}&noop=true", 500)
            .setHeader("asset.type", simple(MediaType.APPLICATION_XML))
        .when(header("file.extension").isEqualTo("pdf"))
            .pollEnrich("file:///{{application.fileStorage.basePath}}/pdf?fileName=${body}&noop=true", 500)
            .setHeader("asset.type", simple("application/pdf"))
    .end()
    .convertBodyTo(File.class)
    .process(multipartProcessor) // add file ass attachment to multipart body and set it as body
    .bean(responseProvider, "getResponse(${body}, 200)");

UPD3
我正在尝试实现自定义处理器以使用带动态文件名的PollingConsumer:

@Override
public void process(Exchange exchange) throws Exception {
    Long timeout = exchange.getIn().getHeader("file.timeout", Long.class);
    if (enrichUri == null) {
        throw new FileNotFoundException("'file.url' header not set");
    }

    CamelContext context = exchange.getContext();
    Endpoint endpoint = context.getEndpoint(enrichUri);
    PollingConsumer consumer = endpoint.createPollingConsumer();
    consumer.start();

    Exchange consumedExchange;
    try {
        if (timeout == null || timeout < 0) {
            consumedExchange = consumer.receive();
        } else if (timeout == 0) {
            consumedExchange = consumer.receiveNoWait();
        } else {
            consumedExchange = consumer.receive(timeout);
        }
    } catch (Exception e) {
        throw new AssetNotFoundException(e);
    } finally {
        consumer.stop();
    }
    exchange.getIn().setBody(consumedExchange.getIn().getBody());
}

现在它在第一个响应时返回文件内容,但在每个后续请求中,我得到了上面日志消息的永久循环:

DEBUG o.a.c.c.f.FileConsumer - Took 0.000 seconds to poll <base path>\xml

UPD4
我已经实现了动态路由,它在处理之前添加并在之后删除。 Apache Camel论坛的this帖子中介绍了此方法。 Route使用上面的处理器来使用文件。结果是相同的

1 个答案:

答案 0 :(得分:9)

简单的方法往往是最好的方式。在这种情况下,我拒绝处理Apache Camel文件组件并实现了以下处理器:

public class FileLoadingProcessor implements Processor {

@Override
public void process(Exchange exchange) throws Exception {
    String filename = exchange.getIn().getBody(String.class); // message body contains filename
    String filePath = exchange.getIn().getHeader("fileprocessor.filepath", String.class);

    if (filePath == null || filename == null) {
        // throw some custom exception
    }

    URI uri = new URI(filePath.concat(filename));
    File file = new File(uri);

    if (!file.exists()) {
        throw new FileNotFoundException(String.format("File %s not found on %s", filename, filePath));
    }

    exchange.getIn().setBody(file);
}

现在它的工作就像一个魅力