Extending FileProducer in Camel 2.2.0

Currently there is no documentation for Apache Camel 2.2.0 on the apache camel website.  This makes using the latest version rather more time consuming than desirable.  I thought that someone must have posted a howto or a tutorial but I was mistaken 😦

Many of the files have been replaced by generic versions and there isn’t any notes on how to use them.  So I’m going to post my discoveries here.

I needed to extend the FileProducer so that I could create a secondary file (putfile) whenever a file is sent.  This file is just to inform the system that a file has been created at another location.  So I Extended the GenericFileProducer which also required the extension of the FileComponent and the FileEndPoint.

I was puzzled as to what type to use in the generic classes.  Taking a look at a signature in the FileComponent clarified the issue:

protected GenericFileEndpoint buildFileEndpoint(String uri, String remaining, Map parameters) throws Exception

So I went ahead and used File as the type.

I wanted to save the putfile to a different location so I did this in the FileProducer by extending it. Here you can see where I have overridden the process method in order that the additional file may be constructed:

public void process(final Exchange exchange) throws Exception {
try {
process(exchange, false);
} catch (Exception ex) {
if (backupPutFileDir != null) {
log.warn("Error on main server, using backup server. ("+ ex.getMessage() +")");
process(exchange, true);
} else {
throw ex;
private void process(final Exchange exchange, final boolean useBackupServer) throws Exception {
boolean contentUnchanged = false;
((PutFileEndpoint) getEndpoint()).setUseBackupPath(useBackupServer);
final Object header = exchange.getIn().getHeader(PutFileComponent.EXCHANGE_CAMELFILENAME, String.class);
final String contentFileName = (String) header;
final String transactionId = exchange.getIn().getHeader(TRANSACTION_ID_HEADER, String.class);

if (((PutFileEndpoint) getEndpoint()).checkChanged()) {
String newContents = exchange.getIn().getBody().toString();
String destinationFileName = createFileName(exchange);
File destFile = new File(destinationFileName);
try {
if (destFile.exists()
&& newContents.equals(FileUtils.readFileToString(destFile))) {
contentUnchanged = true;
catch (Exception e) {
log.info("Unable to compare with destination file, so assuming it has changed");

if (contentUnchanged) {
log.info("Skipping file "+contentFileName
+" because contents haven't changed.");
txlog.info(transactionId+" SKIPPED "+contentFileName);
} else {
// Now the file has been written by the super above, create the
// corresponding putfile
File dir = (useBackupServer ? backupPutFileDir : putFileDir);
File putFile = new File(dir, createPutFileName());
File nameToWriteInPut = new File(dir, contentFileName);
FileUtils.writeStringToFile(putFile, nameToWriteInPut.getPath());
txlog.info(transactionId+" WRITTEN "+contentFileName);

So how does this class get called at all? Well it all starts from the FileComponent. I’ve extended this too and in order to make use of it you need to add it to your camel context either like this:

Create a file that indicates the class of your component. I wanted the word putfile to point to my PutFileComponent (extention of FileComponent so I put this in the contents of the file:


Then I saved in this location:

or you can simply add it in code like this:

CamelContext context = new DefaultCamelContext();
context.addComponent("putfile", new PutFileComponent());

Now the method buildFileEndPoint can be used to tie up all the extended classes:

public GenericFileEndpoint buildFileEndpoint(String uri, String remaining, Map parameters) throws Exception {
// the starting directory must be a static (not containing dynamic expressions)
if (remaining.indexOf("${") != -1) {
throw new IllegalArgumentException("Invalid directory: " + remaining
+ ". Dynamic expressions with ${ } placeholders is not allowed."
+ " Use the fileName option to set the dynamic expression.");

File file = new File(remaining);
PutFileEndpoint result = new PutFileEndpoint(uri, this);
GenericFileConfiguration config = new GenericFileConfiguration();
return result;


2 thoughts on “Extending FileProducer in Camel 2.2.0

  1. Claus Ibsen


    What do you mean with no documentation on the Camel web site?

    There is a zillion wiki pages. The pdf manual is 578 pages.

    And when you feel its to painful to do something, then usually there is a better way with Camel 🙂

    For example you could just use a bean with ProducerTemplate to save the original file and then afterwards save the PUT file. That would be much simpler than creating your own File component.

  2. dorothydorothy Post author

    Well there is the javadoc for the source but nothing else specific to the new classes.

    Thanks for the tip about the bean and the ProducerTemplate. I thought that I might as well share what I have done anyway as someone else might need to extend one of those classes.

    I must find a way to attach the java files in full. I guess that that might have to wait until I set up my own website again and install wordpress there.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s