0

I am reading the file from remote directory using SFTP. I am able to get file by stream using outbound gateway, and move it to archive folder even.

I am processing the data in file but if there is some issue in data then I am throwing an error. I do not want to rename the file if there is any error thrown while processing the data, how can I achieve that. It will be very helpful if I can get some good practices for having error handler while using spring integration.

.handle(Sftp.outboundGateway(sftpSessionFactory(), GET, "payload.remoteDirectory + payload.filename").options(STREAM).temporaryFileSuffix("_reading"))
.handle(readData(),c->c.advice(afterReading()))
.enrichHeaders(h -> h
        .headerExpression(FileHeaders.RENAME_TO, "headers[file_remoteDirectory] + 'archive/' + headers[file_remoteFile]")
        .headerExpression(FileHeaders.REMOTE_FILE, "headers[file_remoteFile]")
        .header(FileHeaders.REMOTE_DIRECTORY, "headers[file_remoteDirectory]"))
.handle(Sftp.outboundGateway(sftpSessionFactory(), MV, "headers[file_remoteDirectory]+headers[file_remoteFile]").renameExpression("headers['file_renameTo']"))
.get();

@Bean
    public ExpressionEvaluatingRequestHandlerAdvice afterReading() {
        ExpressionEvaluatingRequestHandlerAdvice advice = new ExpressionEvaluatingRequestHandlerAdvice();
        advice.setSuccessChannelName("successReading.input");
        advice.setOnSuccessExpressionString("payload + ' was successful streamed'");
        advice.setFailureChannelName("failureReading.input");
        advice.setOnFailureExpressionString("payload + ' was bad, with reason: ' + #exception.cause.message");
        advice.setTrapException(true);
        advice.setPropagateEvaluationFailures(true);
        return advice;
    }

    @Bean
    public IntegrationFlow successReading() {
        return f -> f.log();
    }

    @Bean
    public IntegrationFlow failureReading() {
        return f -> f.log(ERROR);
    }


public GenericHandler readData() {
return new GenericHandler() {
    @Override
    public Object handle(Object o, Map map) {
        InputStream file = (InputStream) o;
        String fileName = (String) map.get(REMOTE_FILE);
        try {
            // processing data
        } catch (Exception e) {
            return new SftpException(500, String.format("Error while processing the file %s because of  Error: %s and reason %s", fileName, e.getMessage(), e.getCause()));
        }
        Closeable closeable = (Closeable) map.get(CLOSEABLE_RESOURCE);
        if (closeable != null) {
            try {
                closeable.close();
                file.close();
            } catch (Exception e) {
                logger.error(String.format("Session didn`t get closed after reading the stream data for file %s and error %s"), fileName, e.getMessage());
            }
        }
        return map;
    }
    };
}

Updated

David
  • 507
  • 2
  • 6
  • 14

1 Answers1

0

Add an ExpressionEvaluatingRequestHandlerAdvice to the .handler() endpoint .handle(readData(), e -> e.advice(...)).

The final supplied advice class is the o.s.i.handler.advice.ExpressionEvaluatingRequestHandlerAdvice. This advice is more general than the other two advices. It provides a mechanism to evaluate an expression on the original inbound message sent to the endpoint. Separate expressions are available to be evaluated, after either success or failure. Optionally, a message containing the evaluation result, together with the input message, can be sent to a message channel.

Gary Russell
  • 166,535
  • 14
  • 146
  • 179
  • I have added the advice as suggested(updated in question) and referred to [link](https://stackoverflow.com/questions/47742953/how-to-move-files-using-expressionevaluatingrequesthandleradvice) as well but I am not able to understand where I can stop the renaming as the flow is going to success channel in case I am throwing an error in service. Apologies in case I have asked trivial question as I am new to Spring integration. – David May 22 '19 at 00:52
  • That's not possible; if the advised handler throws an exception, the alternate path is taken; I suggest you run in a debugger to figure out what's wrong. – Gary Russell May 22 '19 at 12:57
  • I hope you have refereed to the updated code in question. I have debugged as well and I can see when I am throwing error from readData() method it is always going in success channel in advise. I have added a filter after .handle(readData(),c->c.advice(afterReading())) to check if the message is containing error instance or not, this is working for me and I think this is not the riht way to do. – David May 23 '19 at 00:01