Reputation: 75
I am new to Spring integration. I've this requirement to first move a file from /files folder to /process folder in SFTP location and then copy that file to local. I am suggested to use gateway and configuration has to be in java using annotations. I have tried seeking for answers here on stackoverflow but couldn't find something relevant. However I was able to copy the file using @InboundChannelAdapter and by configuring other beans.
Below is the code I have written so far
Configuration public class SftpConfiguration {
@Value("${ftp.file.host}")
private String host;
@Value("${ftp.file.port")
private int port;
@Value("${ftp.file.user")
private String user;
@Value("${ftp.file.password")
private String password;
@Value("${directorry.file.remote")
private String remoteDir;
@Value("${directorry.file.in.pollerDelay")
final private String pollerDelay = "1000";
@Value("${directory.file.remote.move}")
private String toMoveDirectory;
@Bean
public SessionFactory<LsEntry> sftpSessionFactory() {
DefaultSftpSessionFactory factory = new DefaultSftpSessionFactory(true);
factory.setHost(host);
factory.setPort(port);
factory.setUser(user);
factory.setPassword(password);
factory.setAllowUnknownKeys(true);
return new CachingSessionFactory<LsEntry>(factory);
}
@Bean
public SftpInboundFileSynchronizer sftpInboundFileSynchronizer() {
SftpInboundFileSynchronizer fileSynchronizer = new SftpInboundFileSynchronizer(sftpSessionFactory());
fileSynchronizer.setDeleteRemoteFiles(false);
fileSynchronizer.setRemoteDirectory(remoteDir);
fileSynchronizer.setFilter(new SftpSimplePatternFileListFilter("*.xlsx"));
return fileSynchronizer;
}
@Bean
@InboundChannelAdapter(channel = "sftpChannel", poller = @Poller(fixedDelay = pollerDelay))
public MessageSource<File> sftpMessageSource() {
SftpInboundFileSynchronizingMessageSource source = new SftpInboundFileSynchronizingMessageSource(
sftpInboundFileSynchronizer());
source.setLocalDirectory(new File("ftp-inbound"));
source.setAutoCreateLocalDirectory(true);
source.setLocalFilter(new AcceptOnceFileListFilter<File>());
return source;
}
@Bean
@ServiceActivator(inputChannel = "sftpChannel")
public MessageHandler handler() {
return new MessageHandler() {
@Override
public void handleMessage(Message<?> message) throws MessagingException {
try {
new FtpOrderRequestHandler().handle((File) message.getPayload());
} catch (IOException e) {
e.printStackTrace();
}
}
};
}
@Bean
@ServiceActivator(inputChannel = "sftpChannel")
public MessageHandler handlerOut() {
return new SftpOutboundGateway(sftpSessionFactory(), "mv", toMoveDirectory);
}
}
I will appreciate any tips or suggestion . Thanks.
Upvotes: 1
Views: 10273
Reputation: 75
I tried and the following worked for me.
@Configuration
@EnableIntegration
public class SftpConfiguration {
@Value("${config.adapter.ftp.host}")
private String host;
@Value("${config.adapter.ftp.port}")
private int port;
@Value("${config.adapter.ftp.user}")
private String user;
@Value("${config.adapter.ftp.password}")
private String password;
@Autowired
private FtpOrderRequestHandler handler;
@Autowired
ConfigurableApplicationContext context;
@Value("${config.adapter.ftp.excel.sourceFolder}")
private String sourceDir;
@Value("${config.adapter.ftp.excel.localFolder}")
private String localDir;
@Value("${config.adapter.ftp.excel.backupFolder}")
private String backupDir;
@Value("${config.adapter.ftp.statusExcel.destinationFolder}")
private String statusDest;
private static final Logger LOGGER = LoggerFactory.getLogger(SftpConfiguration.class);
@Bean
public SessionFactory<LsEntry> sftpSessionFactory() {
DefaultSftpSessionFactory factory = new DefaultSftpSessionFactory(true);
factory.setHost(host);
factory.setPort(port);
factory.setUser(user);
factory.setPassword(password);
factory.setAllowUnknownKeys(true);
return new CachingSessionFactory<LsEntry>(factory);
}
@Bean
public SftpInboundFileSynchronizer sftpInboundFileSynchronizer() {
SftpInboundFileSynchronizer fileSynchronizer = new SftpInboundFileSynchronizer(sftpSessionFactory());
fileSynchronizer.setDeleteRemoteFiles(true);
fileSynchronizer.setRemoteDirectory(sourceDir);
fileSynchronizer.setFilter(new SftpSimplePatternFileListFilter("*.xlsx"));
return fileSynchronizer;
}
@Bean
@InboundChannelAdapter(channel = "sftpChannel", poller = @Poller(cron = "${config.cron.cataligent.order}"), autoStartup = "true")
public MessageSource<File> sftpMessageSource() {
SftpInboundFileSynchronizingMessageSource source = new SftpInboundFileSynchronizingMessageSource(
sftpInboundFileSynchronizer());
source.setLocalDirectory(new File(localDir));
source.setAutoCreateLocalDirectory(true);
source.setLocalFilter(new AcceptOnceFileListFilter<File>());
return source;
}
@Bean
@ServiceActivator(inputChannel = "sftpChannel")
public MessageHandler handlerOrder() {
return new MessageHandler() {
@Override
public void handleMessage(Message<?> message) throws MessagingException {
try {
SFTPGateway gateway = context.getBean(SFTPGateway.class);
final File orderFile = (File) message.getPayload();
gateway.sendToSftp(orderFile);
LOGGER.debug("{} is picked by scheduler and moved to {} folder",orderFile.getName(),backupDir);
handler.handle((File) message.getPayload());
handler.deleteFileFromLocal((File) message.getPayload());
LOGGER.info("Processing of file {} is completed",orderFile.getName());
} catch (IOException e) {
LOGGER.error("Error occurred while processing order file exception is {}",e.getMessage());
}
}
};
}
@Bean
@ServiceActivator(inputChannel = "sftpChannelDest")
public MessageHandler handlerOrderBackUp() {
SftpMessageHandler handler = new SftpMessageHandler(sftpSessionFactory());
handler.setRemoteDirectoryExpression(new LiteralExpression(backupDir));
return handler;
}
@Bean
@ServiceActivator(inputChannel = "sftpChannelStatus")
public MessageHandler handlerOrderStatusUS() {
SftpMessageHandler handler = new SftpMessageHandler(sftpSessionFactory());
handler.setRemoteDirectoryExpression(new LiteralExpression(statusDest));
return handler;
}
@MessagingGateway
public interface SFTPGateway {
@Gateway(requestChannel = "sftpChannelDest")
void sendToSftp(File file);
@Gateway(requestChannel = "sftpChannelStatus")
void sendToSftpOrderStatus(File file);
}
}
I have used this for picking up a file from SFTP location. Saving it at local. Then moving the file to backup folder and then processing the whole file. After processing deleted the file from the local.
I have used gateway(@MessagingGateway) for file movement and I have two different methods in that interface. One for moving the same file to backup folder and other method is to move another file(a status file) in my code to desired SFTP location. I've tried to keep the code clean for better understanding.
Upvotes: 1
Reputation: 121177
Right, you need to use @Bean
with the @InboundChannelAdapter
for the SftpInboundFileSynchronizingMessageSource
to download files from the remote /process
folder to local directory. This is done on the poller basis and is a separate process, fully not related to the move operation. That move logic you can perform via FtpOutboundGateway
with the MV
command:
The mv command has no options.
The expression attribute defines the "from" path and the rename-expression attribute defines the "to" path. By default, the rename-expression is
headers['file_renameTo']
. This expression must not evaluate to null, or an emptyString
. If necessary, any remote directories needed will be created. The payload of the result message isBoolean.TRUE
. The original remote directory is provided in thefile_remoteDirectory
header, and the filename is provided in thefile_remoteFile
header. The new path is in thefile_renameTo
header.
This one you have to use via:
@Bean
@ServiceActivator(inputChannel = "sftpChannel")
public MessageHandler handler() {
return new SftpOutboundGateway(ftpSessionFactory(), "mv", "'my_remote_dir/my_file'");
}
Upvotes: 0