После долгих поисков оказалось, что такой простой штуки, как слежение за изменениями в отдельном файле, в Camel нету :( Вроде бы логично все - компонент file://mydirectory?fileName=myFile.txt. Изменился файл - послали Exchange. Вот не тут-то было. Слушать можно только появление файлов в директории. После отправки соотв. сообщения файлы удаляются.
Но выход, как всегда, есть. Для этого нам нужен самый последний Camel (см почему) и немножечко отваги:
package com.anydoby.camel;
import java.io.File;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.camel.spi.IdempotentRepository;
public class FileLastModifiedRepository implements IdempotentRepository<String> {
private final Map<String, FileLastModified> cache = new ConcurrentHashMap<String, FileLastModified>();
public boolean add(final String key) {
final File file = new File(key);
final long newLastModified = file.lastModified();
final FileLastModified lastModified = new FileLastModified(newLastModified, file);
final FileLastModified put = this.cache.put(key, lastModified);
return put == null || put.previousLastModified < newLastModified;
}
public boolean confirm(final String key) {
return true;
}
public boolean contains(final String key) {
final boolean containsKey = this.cache.containsKey(key);
if (containsKey) {
final FileLastModified lastModified = this.cache.get(key);
final long newLastModified = lastModified.fileReference.lastModified();
return newLastModified == lastModified.previousLastModified;
} else {
return false;
}
}
public boolean remove(final String key) {
return this.cache.remove(key) != null;
}
private static class FileLastModified {
public final long previousLastModified;
public final File fileReference;
FileLastModified(final Long previousLastModified, final File fileReference) {
this.previousLastModified = previousLastModified;
this.fileReference = fileReference;
}
}
}
Подход такой. В file компоненте можно сказать idempotent=true - это значит дубликатные сообщения фильтруются фреймворком и не доставляются процессорам. А то, что мы видим выше, это репозиторий для сообщений, который использует File.lastModified как критерий "дубликатности". В общем, эффект тот, которого мы хотим - будут приходить сообщения о том же файле, но только когда он изменился.
Вот такой маршрут нужно написать, чтобы это заработало:
from(
"file:target?noop=true&fileName=test.txt&initialDelay=0&delay=500&idempotentRepository=#fileLastModifiedRepository").process(processor());
Естественно, наш репозиторий придется объявить как Spring bean.
Вот тут можно посмотреть юнит тест с демонстрацией, как все это работает.
