Tag Archives: Camel

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:

@Override
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;
}
}
}
@SuppressWarnings("unchecked")
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 {
super.process(exchange);
// Now the file has been written by the super above, create the
// corresponding putfile
File dir = (useBackupServer ? backupPutFileDir : putFileDir);
FileUtils.forceMkdir(dir);
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:

class=com.bbc.newsi.feeds.common.camel.components.PutFileComponent

Then I saved in this location:
META-INF\services\org\apache\camel\component\putfile

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:

@Override
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);
result.setFile(file);
GenericFileConfiguration config = new GenericFileConfiguration();
config.setDirectory(file.getPath());
result.setConfiguration(config);
return result;
}

Advertisements