Spring Integration – Sending files over SFTP
Spring Integration is a powerful extension of the Spring Framework designed to support the implementation of enterprise integration patterns in a Spring-based application. It provides a set of components and APIs for building messaging solutions and integrating disparate systems within an application.
At its core, Spring Integration leverages the concept of message-driven architectures, where components communicate by sending and receiving messages through channels. It enables the implementation of complex integration scenarios by providing support for various communication protocols, message routing, transformation, and mediation.
Key components of Spring Integration include:
- Message: The fundamental unit of communication in Spring Integration, containing data and headers.
- Channel: Acts as a conduit for messages to flow between components. Channels can be direct, point-to-point, publish-subscribe, etc.
- Message Endpoint: Represents the integration logic that consumes or produces messages from or to the messaging system.
- Message Handler: Components responsible for processing incoming messages.
- Message Source: Represents an input channel adapter that generates messages.
- Message Transformer: Converts or transforms messages from one format to another.
- Message Router: Determines the path of the message based on predefined criteria.
- Message Filter: Evaluates messages and decides whether to allow them to pass through or not.
- Service Activator: Invokes a service or method with the message payload.
Lets see the steps for sending files over SFTP using Spring Integration.
i) Include the required below dependency
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-sftp</artifactId>
</dependency>
ii) Configuration to set up integration flow
package com.example.springintegrationsftp.config;
import java.io.File;
import org.apache.sshd.sftp.client.SftpClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.expression.common.LiteralExpression;
import org.springframework.integration.config.EnableIntegration;
import org.springframework.integration.annotation.Gateway;
import org.springframework.integration.annotation.MessagingGateway;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.file.FileNameGenerator;
import org.springframework.integration.file.remote.session.CachingSessionFactory;
import org.springframework.integration.file.remote.session.SessionFactory;
import org.springframework.integration.sftp.outbound.SftpMessageHandler;
import org.springframework.integration.sftp.session.DefaultSftpSessionFactory;
import org.springframework.integration.sftp.session.SftpRemoteFileTemplate;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHandler;
@Configuration
@EnableIntegration
public class SftpConfig {
@Value("${sftp.host}")
private String host;
@Value("${sftp.user}")
private String user;
@Value("${sftp.password}")
private String password;
@Bean
public SessionFactory<SftpClient.DirEntry> sftpSessionFactory() {
DefaultSftpSessionFactory factory = new DefaultSftpSessionFactory(true);
factory.setHost(host);
factory.setPort(22);
factory.setUser(user);
factory.setPassword(password);
factory.setAllowUnknownKeys(true);
return new CachingSessionFactory<>(factory);
}
@Bean
@ServiceActivator(inputChannel = "toSftpChannel")
public MessageHandler handler() {
SftpMessageHandler handler = new SftpMessageHandler(sftpSessionFactory());
handler.setRemoteDirectoryExpression(new LiteralExpression("/"));
handler.setLoggingEnabled(true);
handler.setFileNameGenerator(new FileNameGenerator() {
@Override
public String generateFileName(Message<?> message) {
if (message.getPayload() instanceof File) {
return ((File) message.getPayload()).getName();
} else throw new IllegalArgumentException("File expected in message payload");
}
});
return handler;
}
@MessagingGateway(asyncExecutor = "sftpAsync")
public interface CustomGateway {
@Gateway(requestChannel = "toSftpChannel")
void sendToSftp(File file);
}
@Bean
public AsyncTaskExecutor sftpAsync() {
SimpleAsyncTaskExecutor simpleAsyncTaskExecutor = new SimpleAsyncTaskExecutor();
simpleAsyncTaskExecutor.setThreadNamePrefix("sftp-exec-");
return simpleAsyncTaskExecutor;
}
}
iii) Define Service to invoke the file transfer
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource;
import org.springframework.stereotype.Service;
import com.example.springintegrationsftp.config.SftpConfig;
@Service
public class SftpService {
@Autowired
SftpConfig.CustomGateway sftpGateway;
public void uploadFileToSftp() {
sftpGateway.sendToSftp(new FileSystemResource("D://sftp.txt").getFile());
}
}
iv) Define REST API to invoke the file transfer
@RestController
public class SftpController {
@Autowired
SftpService service;
@GetMapping("/sendFile")
public void sendFile() {
service.uploadFileToSftp();
}
}
In the internet found this free SFTP server(https://sftpcloud.io/tools/free-sftp-server) which we will be using to test sending file over SFTP.
Now we can hit our endpoint http://localhost:8080/sendFile to initiate the SFTP of file.
After the API is invoked could see the file in the SFTP server using the any SFTP client like winscp.
For complete source code: https://github.com/MMahendravarman/Springboot_Examples
Leave a Reply