Русский English Тэги View Sergey Zolotaryov's profile on LinkedIn Вход
Camel. Как следить за изменениями в файле.
Постоянная ссылка 28-07-2010 anydoby java camel

После долгих поисков оказалось, что такой простой штуки, как слежение за изменениями в отдельном файле, в 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.

Вот тут можно посмотреть юнит тест с демонстрацией, как все это работает.

Добавить комментарий

Предыдущая статья Переиспользуемые свойства в Spring Следующая статья Новое и улучшенное