Reputation: 315
In our application there are huge number of files downloaded from remote machine to local machine (server where code is running). We have opted to use Spring SFTP to do the download. Using below code I am able to download file from remote machine to local.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-sftp="http://www.springframework.org/schema/integration/sftp"
xsi:schemaLocation="http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration/sftp http://www.springframework.org/schema/integration/sftp/spring-integration-sftp.xsd">
<import resource="SftpSampleCommon.xml"/>
<int:gateway id="downloadGateway" service-interface="com.rizwan.test.sftp_outbound_gateway.DownloadRemoteFileGateway"
default-request-channel="toGet"/>
<int-sftp:outbound-gateway id="gatewayGet"
local-directory="C:\Users\503017993\Perforce\rizwan.shaikh1_G7LGTPC2E_7419\NGI\DEV\Jetstream_Branches\C360_Falcon2_1_Main\sftp-outbound-gateway"
session-factory="sftpSessionFactory"
request-channel="toGet"
remote-directory="/si.sftp.sample"
command="get"
command-options="-P"
expression="payload"
auto-create-local-directory="true"
session-callback="downloadCallback">
<int-sftp:request-handler-advice-chain>
<int:retry-advice />
</int-sftp:request-handler-advice-chain>
</int-sftp:outbound-gateway>
<!-- reply-channel="toRm" -->
<int:gateway id="deleteGateway" service-interface="com.rizwan.test.sftp_outbound_gateway.DeleteRemoteFileGateway"
default-request-channel="toRm"/>
<int-sftp:outbound-gateway id="gatewayRM"
session-factory="sftpSessionFactory"
expression="payload"
request-channel="toRm"
command="rm">
<int-sftp:request-handler-advice-chain>
<int:retry-advice />
</int-sftp:request-handler-advice-chain>
</int-sftp:outbound-gateway>
</beans>
Java code
ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext(
"classpath:/META-INF/spring-context.xml");
DownloadRemoteFileGateway downloadGateway = ctx.getBean(DownloadRemoteFileGateway.class);
DeleteRemoteFileGateway deleteGateway = ctx.getBean(DeleteRemoteFileGateway.class);
String downloadedFilePath = downloadGateway.downloadRemoteFile("si.sftp.sample/2ftptest");
System.out.println("downloadedFilePath: " + downloadedFilePath);
Boolean status = deleteGateway.deleteRemoteFile("si.sftp.sample/2ftptest");
System.out.println("deletion status: " + status);
Above code works as expected. It downloads the remote file and then deletes it.
We already have checksum of the downloaded file with us. This checksum is calculated from the remote file. Is it possible to build a mechanism to calculate the checksum of the file after it is downloaded. We need to be able to compare expected checksum with checksum of file received and retry fixed number of times if there is a mismatch.
I am wondering if I can use RetryTemplate
like below. It is untested pseudo code.
class Test {
@Autowired
DownloadRemoteFileGateway downloadGateway;
public void init() {
RetryTemplate template = new RetryTemplate();
ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
backOffPolicy.setInitialInterval(Long.parseLong(initialInterval));
backOffPolicy.setMaxInterval(Long.parseLong(initialInterval));
template.setRetryPolicy(new SimpleRetryPolicy(Integer.parseInt(maxAttempts), exceptionMap));
template.setBackOffPolicy(backOffPolicy);
}
void foo(){
Object result = template.execute(new RetryCallback() {
@Override
public String doWithRetry(RetryContext retryContext) throws Exception {
//Calculate received file checksum and compare with expected checksum
if(mismatch) {
downloadGateway.downloadRemoteFile(remoteFileName);
}
}, new RecoveryCallback() {
//same logic
});
}//foo
}//Test
My question is how do I make my method foo() execute after file download completes. Is it also possible to get downloaded filename in foo().
Upvotes: 1
Views: 1262
Reputation: 121212
I think what you need definitely can be done with AOP Advices. More over with the chain of them, where indeed the RequestHandlerRetryAdvice
should be first to start a retry loop. The next Advice I would suggest to use as ExpressionEvaluatingRequestHandlerAdvice
with its onSuccessExpression
and propagateOnSuccessEvaluationFailures = true
combination. This way you perform that checksum validation in the onSuccessExpression
and if it doesn't match, throw an exception. That exception is going to be caught by the previous in stack RequestHandlerRetryAdvice
and the retry logic will be performed.
See their JavaDocs and Reference Manual on the matter.
Also we have some Sample project to understand things better.
Upvotes: 1