Spring 如何在复合触发器上设置覆盖?
我有一个Spring集成应用程序,它通常每天使用cron触发器通过SFTP轮询一个文件。但是如果它没有找到它期望的文件,它应该通过周期性触发器每隔x分钟轮询一次,直到y尝试。为此,我使用以下组件:Spring 如何在复合触发器上设置覆盖?,spring,spring-integration,Spring,Spring Integration,我有一个Spring集成应用程序,它通常每天使用cron触发器通过SFTP轮询一个文件。但是如果它没有找到它期望的文件,它应该通过周期性触发器每隔x分钟轮询一次,直到y尝试。为此,我使用以下组件: @Component public class RetryCompoundTriggerAdvice extends AbstractMessageSourceAdvice { private final static Logger logger = LoggerFactory.getLog
@Component
public class RetryCompoundTriggerAdvice extends AbstractMessageSourceAdvice {
private final static Logger logger = LoggerFactory.getLogger(RetryCompoundTriggerAdvice.class);
private final CompoundTrigger compoundTrigger;
private final Trigger override;
private final ApplicationProperties applicationProperties;
private final Mail mail;
private int attempts = 0;
public RetryCompoundTriggerAdvice(CompoundTrigger compoundTrigger,
@Qualifier("secondaryTrigger") Trigger override,
ApplicationProperties applicationProperties,
Mail mail) {
this.compoundTrigger = compoundTrigger;
this.override = override;
this.applicationProperties = applicationProperties;
this.mail = mail;
}
@Override
public boolean beforeReceive(MessageSource<?> source) {
return true;
}
@Override
public Message<?> afterReceive(Message<?> result, MessageSource<?> source) {
final int maxOverrideAttempts = applicationProperties.getMaxFileRetry();
attempts++;
if (result == null && attempts < maxOverrideAttempts) {
logger.info("Unable to find load file after " + attempts + " attempt(s). Will reattempt");
this.compoundTrigger.setOverride(this.override);
} else if (result == null && attempts >= maxOverrideAttempts) {
mail.sendAdminsEmail("Missing File");
attempts = 0;
this.compoundTrigger.setOverride(null);
}
else {
attempts = 0;
this.compoundTrigger.setOverride(null);
logger.info("Found load file");
}
return result;
}
public void setOverrideTrigger() {
this.compoundTrigger.setOverride(this.override);
}
public CompoundTrigger getCompoundTrigger() {
return compoundTrigger;
}
}
会话工厂是:
@Bean
public SessionFactory<LsEntry> sftpSessionFactory() {
DefaultSftpSessionFactory sftpSessionFactory = new DefaultSftpSessionFactory();
sftpSessionFactory.setHost(applicationProperties.getSftpHost());
sftpSessionFactory.setPort(applicationProperties.getSftpPort());
sftpSessionFactory.setUser(applicationProperties.getSftpUser());
sftpSessionFactory.setPassword(applicationProperties.getSftpPassword());
sftpSessionFactory.setAllowUnknownKeys(true);
return new CachingSessionFactory<LsEntry>(sftpSessionFactory);
}
更新
下面是消息处理程序:
@Bean
@ServiceActivator(inputChannel = "sftpChannel")
public MessageHandler dailyHandler(SimpleJobLauncher jobLauncher, Job job, Mail mail) {
JobRunner jobRunner = new JobRunner(jobLauncher, job, store, mail);
jobRunner.setDaily("true");
jobRunner.setOverwrite("false");
return jobRunner;
}
JobRunner
启动Spring批处理作业。处理完作业后,我的应用程序会查看该文件是否包含当天所需的数据。如果没有,则设置覆盖触发器。这就是触发器的工作方式-只有在触发器触发时,您才有机会更改触发器
由于重置为cron触发器,因此下一个更改机会是触发该触发器时(如果轮询器线程在更改触发器之前被下游流释放)
您是否正在将文件移交给另一个线程(队列通道或执行器)?如果没有,我希望应该应用对触发器的任何更改,因为在下游流返回之前不会调用nextExecutionTime()
如果有线程切换,您没有机会更改触发器。谢谢。是的,这和我能说的不同。这就解释了。在OP更新部分添加了相关代码。不知道如何在不调用决定从
RetryCompoundTriggerAdvice
中重试的逻辑的情况下实现我的目标。不过,逻辑是基于几个因素的,包括读取和比较文件中的所有行(这就是为什么我在Spring批处理作业完成后应用它的原因)。CompoundTriggerAdvice
提供了一些功能。一种可能性是,在处理消息时,在评估文件状态之前,将短期轮询器保持在原位。让服务“确认”该建议一切正常,并在下次投票时更改触发器。处理文件时(确认之前),使用beforeceive()
returnfalse
,取消当前轮询
@Bean
@InboundChannelAdapter(autoStartup="true", channel = "sftpChannel", poller = @Poller("pollerMetadata"))
public SftpInboundFileSynchronizingMessageSource sftpMessageSource() {
SftpInboundFileSynchronizingMessageSource source =
new SftpInboundFileSynchronizingMessageSource(sftpInboundFileSynchronizer());
source.setLocalDirectory(applicationProperties.getScheduledLoadDirectory());
source.setAutoCreateLocalDirectory(true);
CompositeFileListFilter<File> compositeFileFilter = new CompositeFileListFilter<File>();
compositeFileFilter.addFilter(new LastModifiedFileListFilter());
compositeFileFilter.addFilter(new FileSystemPersistentAcceptOnceFileListFilter(store, "dailyfilesystem"));
source.setLocalFilter(compositeFileFilter);
source.setCountsEnabled(true);
return source;
}
@Bean
public PollerMetadata pollerMetadata(RetryCompoundTriggerAdvice retryCompoundTriggerAdvice) {
PollerMetadata pollerMetadata = new PollerMetadata();
List<Advice> adviceChain = new ArrayList<Advice>();
adviceChain.add(retryCompoundTriggerAdvice);
pollerMetadata.setAdviceChain(adviceChain);
pollerMetadata.setTrigger(compoundTrigger());
pollerMetadata.setMaxMessagesPerPoll(1);
return pollerMetadata;
}
@Bean
public CompoundTrigger compoundTrigger() {
CompoundTrigger compoundTrigger = new CompoundTrigger(primaryTrigger());
return compoundTrigger;
}
@Bean
public CronTrigger primaryTrigger() {
return new CronTrigger(applicationProperties.getSchedule());
}
@Bean
public PeriodicTrigger secondaryTrigger() {
return new PeriodicTrigger(applicationProperties.getRetryInterval());
}
@Bean
@ServiceActivator(inputChannel = "sftpChannel")
public MessageHandler dailyHandler(SimpleJobLauncher jobLauncher, Job job, Mail mail) {
JobRunner jobRunner = new JobRunner(jobLauncher, job, store, mail);
jobRunner.setDaily("true");
jobRunner.setOverwrite("false");
return jobRunner;
}