WatchEventType.DELETE не работает
То, что я хотел бы сделать, это отслеживать удаленные файлы и применять определенную логику вокруг этого (получить идентификатор и обновить сущности). Я обнаружил, что мы можем передать список событий наблюдения внутри адаптера канала, включая
FileReadingMessageSource.WatchEventType.DELETE
но когда я удаляю файл из папки, я не вижу никаких сработавших событий, и преобразователь никогда не применяется
@Bean
public IntegrationFlow integrationFlow(FileToMovieTransformer fileToMovieTransformer) {
return this.integrationFlowBuilder()
.transform(fileToMovieTransformer)
.channel(movieHandlerChannel())
.get();
}
private IntegrationFlowBuilder integrationFlowBuilder() {
return IntegrationFlows.from(
Files.inboundAdapter(new File(localFilmFolder))
.autoCreateDirectory(true)
.useWatchService(true)
.watchEvents(FileReadingMessageSource.WatchEventType.CREATE, FileReadingMessageSource.WatchEventType.DELETE)
.patternFilter("*.xml"),
e -> e.poller(Pollers.fixedDelay(10, TimeUnit.SECONDS)
));
}
2 ответа
Я бы сказал, что вы относитесь к DELETE
Неправильный путь:
/**
* Directory entry deleted.
*
* <p> When a directory is registered for this event then the {@link WatchKey}
* is queued when it is observed that an entry is deleted or renamed out of
* the directory. The event {@link WatchEvent#count count} for this event
* is always {@code 1}.
*/
public static final WatchEvent.Kind<Path> ENTRY_DELETE =
new StdWatchEventKind<Path>("ENTRY_DELETE", Path.class);
Так что уже нет ничего, что можно было бы выбросить в качестве сообщения для нижестоящих. Мы определенно поговорим здесь о FileReadingMessageSource
, Но с DELETE
читать больше нечего. Я что-то пропустил?
И вот что мы имеем в Документах:
ENTRY_DELETE
события влияют наResettableFileListFilter
реализации и, следовательно, их файлы предоставляются дляremove()
операция. Это означает, что (когда это событие включено), фильтры, такие какAcceptOnceFileListFilter
удалит файл, а это означает, что, если появится файл с таким же именем, он пройдет фильтр и будет отправлен как сообщение.
Поэтому добиться того, что вы хотели бы сделать в случае DELETE
событие, вам нужно реализовать ResettableFileListFilter
и вместе с SimplePatternFileListFilter
вы должны объединить их в CompositeFileListFilter
,
Когда файл удален, это DELETE
событие генерируется, и мы получаем логику
if (event.kind() == StandardWatchEventKinds.ENTRY_DELETE) {
if (getFilter() instanceof ResettableFileListFilter) {
((ResettableFileListFilter<File>) getFilter()).remove(file);
}
Где упомянутое CompositeFileListFilter
определенно реализует это ResettableFileListFilter
один и делегировать к вашей собственной реализации.
Спасибо за @Artem, вот полный пример кода, который мне подходит
private IntegrationFlowBuilder integrationFlowBuilder() {
final List<FileListFilter<File>> defaultFilters = new ArrayList<>(2);
defaultFilters.add(new IgnoreHiddenFileListFilter());
defaultFilters.add(new AcceptOnceFileListFilter<>());
defaultFilters.add(new SimplePatternFileListFilter("*.xml"));
defaultFilters.add(myCustomRemovalFilter);
CompositeFileListFilter fileListFilter = new CompositeFileListFilter<>(defaultFilters);
return IntegrationFlows.from(
Files.inboundAdapter(new File(localFilmFolder))
.autoCreateDirectory(true)
.filter(fileListFilter)
.useWatchService(true)
.watchEvents(FileReadingMessageSource.WatchEventType.CREATE, FileReadingMessageSource.WatchEventType.DELETE),
e -> e.poller(Pollers.fixedDelay(10, TimeUnit.SECONDS)
));
}
и фильтр выглядит
@Component
public class MyCustomRemovalFilter implements ResettableFileListFilter<File> {
private static final Logger LOGGER = LogManager.getLogger(MyCustomRemovalFilter.class);
@Override
public boolean remove(File xmlFile) {
if (xmlFile == null) {
return true;
}
// TODO you own on removal logic
}
@Override
public List<File> filterFiles(File[] files) {
if (files == null || files.length == 0) {
return Collections.emptyList();
}
return Arrays.asList(files);
}
}