How to prevent duplicate Spring Integration service activations when polling directory

爷,独闯天下 提交于 2019-12-02 11:01:12

问题


I have a Spring Integration directory poller:

<task:executor id="filePollingExecutor" pool-size="1" />
<int:channel id="inboundFilesChannel" datatype="java.io.File" />
<int-file:inbound-channel-adapter id="inboundFilesAdapter" 
      channel="inboundFilesChannel"
      directory="/my/files/queue"
      prevent-duplicates="true">
  <int:poller id="poller" fixed-delay="1000" 
              max-messages-per-poll="1" 
              task-executor="filePollingExecutor" />
</int-file:inbound-channel-adapter>

In response to files appearing in the directory, I have a service activator which invokes a method on a service:

Unfortunately I'm finding that the service is consistently being called twice when a file arrives. Originally I thought this was due to having multiple executor threads, but you may notice above, I attempted to resolve that by tying the poller to a taskExecutor with a pool size of 1.

What I have been finding is that I can workaround the issue by increasing the delay between polls. I think the key is that it's longer than the time it takes to process a file.

<int:poller id="poller" fixed-delay="10000" 
            max-messages-per-poll="100" 
            task-executor="filePollingExecutor" />

However, that feels like a kludge rather than a fix.

Am I missing some configuration that I should be using to prevent duplicates?

It's possibly worth noting that I did try using a nio-locker, but the issue there is that part of the processing involves sending an email with the file attached to it. File locks prevented that from being done, as the file ceased to be readable for the duration of the lock.


回答1:


This answer is based on the tip from Gary Russell in the comments above.

The reason for double-processing of files is that the root and web configs were both initialising file system listeners, and therefore processing each file twice.

My approach to avoiding having the file listeners in multiple contexts was as follows.

First define a web config which only picks up classes under the "web" package.

@Configuration
@ComponentScan(basePackages = { "com.myapp.web" })
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
    @Override
    public void configureDefaultServletHandling(
            DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }
}

Create separate root configs which only load beans which are not in the "web" package. i.e.

@Configuration
@ComponentScan(basePackages = { "com.myapp.services" })
public class ServicesConfig {
}

An additional factor in the configuration that took a little while to work out, was that my servlet filters and web security config needed to be in the 'root' context rather than the web context.



来源:https://stackoverflow.com/questions/25184355/how-to-prevent-duplicate-spring-integration-service-activations-when-polling-dir

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!