My spring integration application reads files from a fileshare, does some processing including api calls etc. In case something goes wrong in between I would like to use a afterRollbakExpression to write the file to a failed directory in the file share/ftp/sftp etc.
I found an example of doing the same to a local file directory as follows,
@Bean
TransactionSynchronizationFactory transactionSynchronizationFactory() {
ExpressionParser parser = new SpelExpressionParser();
ExpressionEvaluatingTransactionSynchronizationProcessor syncProcessor =
new ExpressionEvaluatingTransactionSynchronizationProcessor();
syncProcessor.setBeanFactory(applicationContext.getAutowireCapableBeanFactory());
//afterCommit expression moves the file to a processed directory
syncProcessor.setAfterCommitExpression(parser.parseExpression("payload.renameTo(new java.io.File(@inboundProcessedDirectory.path "
+ " + T(java.io.File).separator + payload.name))"));
//afterRollback expression moves the file to a failed directory
syncProcessor.setAfterRollbackExpression(parser.parseExpression("payload.renameTo(new java.io.File(@inboundFailedDirectory.path "
+ " + T(java.io.File).separator + payload.name))"));
return new DefaultTransactionSynchronizationFactory(syncProcessor);
}
I would like to do the same thing but write the file to the fileshare/ftp/sftp during a rollback scenario and not to a local directory.
I have a messageHandler which I invoke to write files using the integration flow to the smb fileshare. I dont know how do i invoke the following messagehandler as a AfterRollbackExpression,
@Bean(name = SMB_FILE_ERROR_MESSAGE_HANDLER)
public MessageHandler smbMessageHandler() {
FileTransferringMessageHandler<SmbFile> handler =
new FileTransferringMessageHandler<>(smbSessionFactory);
handler.setRemoteDirectoryExpression(
new LiteralExpression("/INPUT/ERROR"));
handler.setFileNameGenerator(m ->
m.getHeaders().get(FileHeaders.FILENAME, String.class) + "." + DateTimeFormatter.ofPattern(dateFormat).format(LocalDateTime.now()));
handler.setAutoCreateDirectory(true);
return handler;
}
You just mark that smbMessageHandler
bean with the @ServiceActivator(inputChannel = "smbStoreChannel")
and this ExpressionEvaluatingTransactionSynchronizationProcessor
may just have a setAfterRollbackChannel(smbStoreChannel)
. So, when rollback happens a failed message is going to be sent to that channel where your FileTransferringMessageHandler
will consume it from the channel and probably send to SMB. Consider also to use a TransactionSynchronizationFactoryBean
for convenience.