WatchEventType.DELETE似乎不起作用

时间:2018-04-19 08:37:04

标签: java spring spring-integration integration-patterns

我想要做的是跟踪删除的文件并在此周围应用某些逻辑(获取id并更新实体)。我发现我们可以在通道适配器中传递监视事件列表,包括

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 个答案:

答案 0 :(得分:1)

我会说你以错误的方式对待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,并将委托给您自己的实现。

答案 1 :(得分:1)

感谢@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);
}
}