Search code examples
springspring-integrationspring-elspring-integration-sftp

Call a bean method with the downloaded filename after file download using sftp outbound gateway


I am using int-sftp:outbound-gateway to download remote files. File download is working. I need to call another method after file is downloaded for both success as well as failure. In that method I need status (success or failure) and name of the file that was requested to be downloaded. Then from that method I will initiate a post download flow depending on the status like - moving file to different location, notifying the user, sending email, etc.

I have used AfterReturningAdviceInterceptor to call my own method defined in MyAfterReturningAdvice which implements AfterReturningAdvice interface. With this my method to initiate the post download flow. It does execute and I do get filename in GenericMessage's payload. My question is, do we have a better way to implement this flow.

I tried using ExpressionEvaluatingRequestHandlerAdvice's onSuccessExpression but from that I cannot call another method. All I can do is manipulate the inputMessage(GenericMessage instance).

In future sprints I will have compare checksum of downloaded file with expected checksum and re-download file for a fixed number of times if there is checksum mismatch. As soon as checksum matches I again need to call post download flow. If the download fails even at last retry, then I need to call another flow (send email, update db, notify user of failure,etc.) I am asking this question just to make sure that my current implementation fits overall requirements.

<int:gateway id="downloadGateway" service-interface="com.rizwan.test.sftp_outbound_gateway.DownloadRemoteFileGateway"
    default-request-channel="toGet"/>

<bean id="myAfterAdvice" class="org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor">
    <constructor-arg>
        <bean class="com.rizwan.test.sftp_outbound_gateway.MyAfterReturningAdvice">
        </bean>
    </constructor-arg>
</bean>

<int-sftp:outbound-gateway id="gatewayGet"
    local-directory="C:\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">
    <int-sftp:request-handler-advice-chain>
        <ref bean="myAfterAdvice" />
    </int-sftp:request-handler-advice-chain>
</int-sftp:outbound-gateway>


public class MyAfterReturningAdvice implements AfterReturningAdvice {

    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        //update db, send email, notify user.
    }
}

Solution

  • The ExpressionEvaluatingRequestHandlerAdvice.onSuccessExpression() is the best choice for you. Its EvaluationContext is BeanFactory-aware, therefore you definitely can call any bean from that expression. The Message provided there as a root object is a good candidate to get an information about a downloaded file.

    So, this is what you can do there:

    <bean class="org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice">
        <property name="onSuccessExpressionString" value="@myBean.myMethod(#root)"/>
    </bean>
    

    The same you can do with the onFailureExpression.

    On the other hand you may even don't need to worry about the bean access from the expression. The ExpressionEvaluatingRequestHandlerAdvice has successChannel and failureChannel options. So, the message with the result can be send there and some <service-activator> with your bean can handle a message on that channel.