2017-07-24 1 views
1

je le fichier SFTP suivant synchroniseur:SftpInboundFileSynchronizer ne se synchronisent pas

@Bean 
public SftpInboundFileSynchronizer sftpInboundFileSynchronizer() { 
    SftpInboundFileSynchronizer fileSynchronizer = new SftpInboundFileSynchronizer(sftpSessionFactory()); 
    fileSynchronizer.setDeleteRemoteFiles(false); 
    fileSynchronizer.setRemoteDirectory(applicationProperties.getSftpDirectory()); 
    CompositeFileListFilter<ChannelSftp.LsEntry> compositeFileListFilter = new CompositeFileListFilter<ChannelSftp.LsEntry>(); 
    compositeFileListFilter.addFilter(new SftpPersistentAcceptOnceFileListFilter(store, "sftp")); 
    compositeFileListFilter.addFilter(new SftpSimplePatternFileListFilter(applicationProperties.getLoadFileNamePattern())); 
    fileSynchronizer.setFilter(compositeFileListFilter); 
    fileSynchronizer.setPreserveTimestamp(true); 
    return fileSynchronizer; 
} 

Lorsque la première application fonctionne, il synchronise le répertoire local avec le répertoire du site SFTP à distance. Cependant, il ne parvient pas à détecter les modifications ultérieures dans les fichiers de répertoire SFTP distants.

Il est prévu au sondage comme suit:

@Bean 
@InboundChannelAdapter(autoStartup="true", channel = "sftpChannel", poller = @Poller("pollerMetadata")) 
public SftpInboundFileSynchronizingMessageSource sftpMessageSource() { 
    SftpInboundFileSynchronizingMessageSource source = 
      new SftpInboundFileSynchronizingMessageSource(sftpInboundFileSynchronizer()); 
    source.setLocalDirectory(applicationProperties.getScheduledLoadDirectory()); 
    source.setAutoCreateLocalDirectory(true); 
    ChainFileListFilter<File> chainFileFilter = new ChainFileListFilter<File>(); 
    chainFileFilter.addFilter(new LastModifiedFileListFilter()); 
    FileSystemPersistentAcceptOnceFileListFilter fs = new FileSystemPersistentAcceptOnceFileListFilter(store, "dailyfilesystem"); 
    fs.setFlushOnUpdate(true); 
    chainFileFilter.addFilter(fs); 
    source.setLocalFilter(chainFileFilter); 
    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()); 
} 

Dans la méthode afterReceive de RetryCompoundTriggerAdvice qui s'étend AbstractMessageSourceAdvice, je reçois un résultat nul après la première manche.

Comment puis-je configurer le synchroniseur de sorte qu'il se synchronise périodiquement (plutôt que juste une fois au démarrage de l'application)?

Mise à jour

J'ai trouvé que lorsque le site SFTP n'a pas de fichier dans son répertoire sur mon démarrage de l'application, les SftpInboundFileSynchronizer synchronisations à chaque intervalle d'interrogation. Donc, je peux voir com.jcraft.jsch des déclarations de journal à chaque sondage. Mais dès qu'un fichier est trouvé sur le site SFTP, il se synchronise pour obtenir ce fichier localement et ne se synchronise plus.

Mise à jour 2

Mes excuses ... voici le code personnalisé:

@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; 

    private boolean expectedMessage; 
    private boolean inProcess; 

    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) { 
     logger.debug("!inProcess is " + !inProcess); 
     return !inProcess; 
    } 

    @Override 
    public Message<?> afterReceive(Message<?> result, MessageSource<?> source) { 

     if (expectedMessage) { 
      logger.info("Received expected load file. Setting cron trigger."); 
      this.compoundTrigger.setOverride(null); 
      expectedMessage = false; 
      return result; 
     } 

     final int maxOverrideAttempts = applicationProperties.getMaxFileRetry(); 

     attempts++; 
     if (result == null && attempts < maxOverrideAttempts) { 
      logger.info("Unable to find file after " + attempts + " attempt(s). Will reattempt"); 
      this.compoundTrigger.setOverride(this.override); 
     } else if (result == null && attempts >= maxOverrideAttempts) { 
      String message = "Unable to find daily file" + 
        " after " + attempts + 
        " attempt(s). Will not reattempt since max number of attempts is set at " + 
        maxOverrideAttempts + "."; 
      logger.warn(message); 
      mail.sendAdminsEmail("Missing Load File", message); 
      attempts = 0; 
      this.compoundTrigger.setOverride(null); 
     } else { 
      attempts = 0; 
      // keep periodically checking until we are certain 
      // that this message is the expected message 
      this.compoundTrigger.setOverride(this.override); 
      inProcess = true; 
      logger.info("Found load file"); 
     } 
     return result; 
    } 

    public void foundExpectedMessage(boolean found) { 
     logger.debug("Expected message was found? " + found); 
     this.expectedMessage = found; 
     inProcess = false; 
    } 

} 
+0

Nous avons besoin de connaître votre logique 'RetryCompoundTriggerAdvice'. On dirait qu'après un succès, vous le tournez dans l'état ne pas interroger du tout en quelque sorte. –

+0

Donc, bien, vous utilisez du code personnalisé dans votre solution et vous ne le partagez pas avec nous, alors attendez-vous à être downvoted et à la proposition de fermeture de question. –

+0

Mes excuses ... Le code personnalisé a été ajouté. – James

Répondre

1

Vous avez la logique:

@Override 
public boolean beforeReceive(MessageSource<?> source) { 
    logger.debug("!inProcess is " + !inProcess); 
    return !inProcess; 
} 

Etudions son JavaDoc:

/** 
* Subclasses can decide whether to proceed with this poll. 
* @param source the message source. 
* @return true to proceed. 
*/ 
public abstract boolean beforeReceive(MessageSource<?> source); 

Et la logique autour de cette méthode:

Message<?> result = null; 
    if (beforeReceive((MessageSource<?>) target)) { 
     result = (Message<?>) invocation.proceed(); 
    } 
    return afterReceive(result, (MessageSource<?>) target); 

Ainsi, nous appelons invocation.proceed() (synchronisation SFTP) que si beforeReceive() retours true. Dans votre cas, ce n'est le cas que si !inProcess.

Dans la mise en œuvre afterReceive() vous avez inProcess = true; dans le cas où vous avez un result - à la première tentative. Et on dirait que vous le réinitialisez à false seulement quand quelqu'un appelle cela foundExpectedMessage().

Alors, qu'attendez-vous de nous comme réponse à votre problème? Il est vraiment dans votre code personnalisé et n'est pas lié au cadre. Désolé ...

+1

Merci pour votre aide. Tu as raison. Il s'avère que je n'ai pas eu mon appel à 'foundExpectedMessage' branché. Donc, il n'a jamais été appelé. Désolé je n'ai pas attrapé ça. – James