3
votes

I've tried to build a route to copy files from one directory to an other directory. But instead of using: from(file://source-directory).to(file://destination-directory) I want to do something like this:

from(direct:start)
  .to(direct:doStuff)
  .to(direct:readDirectory)
  .to(file://destination-folder)

I've done the following stuff:

Route

@Component
public class Route extends AbstractRouteBuilder {
  @Override
  public void configure() throws Exception {
      from("direct:start")
        .bean(lookup(ReadDirectory.class))
        .split(body())
          .setHeader("FILENAME", method(lookup(CreateFilename.class)))
          .to("file:///path/to/my/output/directory/?fileName=${header.FILENAME}");
  }

Processor

@Component
public class ReadDirectory implements CamelProcessorBean {
  @Handler
  public ImmutableList<File> apply(@Header("SOURCE_DIR") final String sourceDir) {
    final File directory = new File(sourceDir);
    final File[] files = directory.listFiles();
    if (files == null) {
      return ImmutableList.copyOf(Lists.<File>newArrayList());
    }
    return ImmutableList.copyOf(files);
  }
}

I can start my route by using the following pseudo-Test (The point is I can manually start my route by producer.sendBodyAndHeader(..))

public class RouteIT extends StandardIT {
  @Produce
  private ProducerTemplate producer;

  @Test
  public void testRoute() throws Exception {
    final String uri = "direct:start";
    producer.sendBodyAndHeaders(uri, InOut, null, header());
  }

  private Map<String, Object> header() {
    final Map<String, Object> header = Maps.newHashMap();
    header.put("SOURCE_DIR", "/path/to/my/input/directory/");
    return header;
  }
}
  • AbstractRouteBuilderextends SpringRouteBuilder
  • CamelProcessorBean is only a Marker-Interface
  • StandardIT loads SpringContext and stuff

The problem is, that I must set the filename. I've read some stuff that camel sets the header CamelFileNameProduced (during the file endpoint). It is a generic string with timestamp and if I don't set the filename - the written files will get this generic string as the filename.

My Question is: Is there a more beautiful solution to copy files (but starting with a direct-endpoint and read the directory in the middle of the route) and keep the filename for the destination? (I don't have to set the filename when I use from("file:source").to("file:destination"), why must I do it now?)

1

1 Answers

2
votes

You can set the file name when you send using the producer template, as long as the header is propagated during the routing between the routes you are all fine, which Camel does by default.

For example

  @Test
  public void testRoute() throws Exception {
    final String uri = "direct:start";
    Map headers = ...
    headers.put(Exchange.FILE_NAME, "myfile.txt");
    producer.sendBodyAndHeaders(uri, InOut, null, headers);
  }

The file component talks more about how to control the file name