使用 Spring SFTP 出站网关时,文件发送到错误的 sftp 位置

mnh*_*ilu 5 spring sftp jsch spring-boot spring-integration-sftp

我们使用 Spring SFTP(出站)和网关将文件传输到多个目的地。但通常很少有文件被发送到错误的目的地。找不到任何线索,因为除了发送文件后的文件计数错误之外,我们的日志中没有收到任何错误。

这是我们的配置:

@Configuration
public class BankWiseSFTPConfig {

    private final ExpressionParser EXPRESSION_PARSER;
    private final BankConfigService bankConfigService;

    public BankWiseSFTPConfig(BankConfigService bankConfigService) {
        this.EXPRESSION_PARSER = new SpelExpressionParser();
        this.bankConfigService = bankConfigService;
    }

    @Bean
    public DelegatingSessionFactory<LsEntry> sessionFactory() {

        List<BankConfigEntity> bankList = bankConfigService.getAll();
        Map<Object, SessionFactory<LsEntry>> factories = new LinkedHashMap<>();

        for (BankConfigEntity bank : bankList) {
            DefaultSftpSessionFactory factory = new DefaultSftpSessionFactory();
            factory.setHost(bank.getSftpHost());
            factory.setUser(bank.getSftpUser());
            factory.setPort(bank.getSftpPort());
            factory.setPassword(bank.getSftpPass());
            factory.setAllowUnknownKeys(true);
            factories.put(bank.getBankName(), factory);
        }
        bankList.clear();

        return new DelegatingSessionFactory<LsEntry>(factories, factories.values().iterator().next());
    }


    @ServiceActivator(inputChannel = "toSftp")
    @Bean
    public SftpMessageHandler handler() {
        SftpMessageHandler handler = new SftpMessageHandler(new SftpRemoteFileTemplate(sessionFactory()));
        handler.setRemoteDirectoryExpression(EXPRESSION_PARSER.parseExpression("headers['path']"));
        return handler;
    }
    
    @MessagingGateway
    public interface SFTPOutboundGateway {
        @Gateway(requestChannel = "toSftp")
        void push(File file, @Header("path") String path);

        @Gateway(requestChannel = "sftpChannel")
        List<String> executeCommand(String path);
    }

    @Bean
    @ServiceActivator(inputChannel = "sftpChannel")
    public MessageHandler messageHandlerLs() {
        SftpOutboundGateway sftpOutboundGateway = new SftpOutboundGateway(sessionFactory(), "ls", "payload");
        sftpOutboundGateway.setOptions("-1 -R");
        return sftpOutboundGateway;
    }
}
Run Code Online (Sandbox Code Playgroud)

以下是我们的推送和文件计数方法:

private void pushReport(String bankName,
                            String destinationPath,
                            String sourcePath,
                            String refundType,
                            List<BankReportEntity> failedBankReportEntities,
                            List<BankReportEntity> pushedFiles,
                            BankReportEntity bankReportEntity) {

        String sftpStatus = SlotBankStatus.BANK_SFTP_INITIATED.name();
        String errorReason = StringUtils.EMPTY;
        String fileName = bankReportEntity.getFileName();
        String filePath = sourcePath + fileName;
        File file = new File(filePath);

        bankReportEntity.setSftpStatus(sftpStatus);
        log.debug("{} :: SFTP Push Initiated for {} and File {}", refundType, bankName, fileName);

        try {
            log.info("{} :: SFTP Push trying for {} and {}", refundType, bankName, file);
            gateway.push(file, destinationPath);
            sftpStatus = SlotBankStatus.BANK_SFTP_COMPLETED.name();
            pushedFiles.add(bankReportEntity);
            log.info("{} :: SFTP Push success for {} and {}", refundType, bankName, file);

        } catch (Exception e) {
            emailService.sendSFTPExceptionEmail(
                    "File push error for file : " + fileName +
                            " and FileTransferType " + bankReportEntity.getFileTransferType() +
                            ". Error : " + e.getLocalizedMessage(),
                    bankName);
            sftpStatus = SlotBankStatus.BANK_SFTP_PENDING.name();
            errorReason = ErrorCode.SFTP_PUSH_FAILED.name();
            failedBankReportEntities.add(bankReportEntity);
            log.error("{} :: File push error for file : {}, Bank {}, FileTransferType {}, Error : {}",
                    refundType,
                    fileName,
                    bankName,
                    bankReportEntity.getFileTransferType(),
                    e.getMessage(),
                    e
            );

        } finally {
            log.info("{} :: SFTP to {} Status Updated for : {}", refundType, bankName, bankReportEntity);
            bankReportEntity.setSftpStatus(sftpStatus);
            bankReportEntity.setErrorReason(errorReason);
        }
    }

    private SFTPPushFileCountDto getSFTPSuccessfulFileCount(
            String bankName,
            String path,
            String refundType,
            List<BankReportEntity> pushedFiles,
            List<BankReportEntity> failedBankReports) {

        int totalSuccessfulPush = pushedFiles.size();
        int totalFailedPush = failedBankReports.size();

        log.info("{} :: getSFTPSuccessfulFileCount() for {}, from {}", refundType, bankName, path);

        try {
            List<String> remoteFiles = gateway.executeCommand(path);

            for (Iterator<BankReportEntity> pushedFilesIterator = pushedFiles.iterator(); pushedFilesIterator.hasNext(); ) {
                BankReportEntity bankReport = pushedFilesIterator.next();
                String fileName = bankReport.getFileName();
                if (!remoteFiles.contains(fileName)) {
                    log.error("getSFTPSuccessfulFileCount() : File not found in remote {}. File: {}", path, fileName);
                    totalFailedPush++;
                    totalSuccessfulPush--;
                    bankReport.setSftpStatus(SlotBankStatus.BANK_SFTP_PENDING.name());
                    bankReport.setErrorReason(ErrorCode.UNKNOWN_ERROR_CODE.name());
                    pushedFilesIterator.remove();
                    failedBankReports.add(bankReport);
                    emailService.sendSFTPExceptionEmail(
                            "File push error for file : " + fileName +
                                    " and FileTransferType " + bankReport.getFileTransferType() +
                                    ". Error : " + ErrorCode.UNKNOWN_ERROR_CODE.description(),
                            bankName);
                }
            }

        } catch (Exception ex) {
            emailService.sendSFTPExceptionEmail("SFTP file count Failed from path " + path, bankName);
            log.error("{} :: getSFTPSuccessfulFileCount() Failed for {}. Error : {}",
                    refundType,
                    bankName,
                    ex.getMessage(),
                    ex);

        }
        return SFTPPushFileCountDto.builder()
                .totalSuccessfulPush(totalSuccessfulPush)
                .totalFailedPush(totalFailedPush)
                .build();
    }
Run Code Online (Sandbox Code Playgroud)

我们无法在我们的环境中重现该问题。

有人可以帮忙吗?