We are using Spring SFTP (outbound) using Gateway to transfer files to multiple destinations. But often, few files are sent to the wrong destination. Can't find any clue as we don't get any error in our log except file count error after sending files.
Here is our configuration:
@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;
}
}
Here are our push and file count methods:
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();
}
We can't reproduce the problem in our environment.
Can anybody help?