[英]Spring Sftp fetch file using outbound gateway within inbound adapter message handler
I am using Inbound Adapter using Java DSL to poll pdf files from the SFTP server.我正在使用使用 Java DSL 的入站适配器从 SFTP 服务器轮询 pdf 文件。 I have a use case where after fetching the pdf file application will fetch the config file present in CSV format with the same name on the SFTP server.
我有一个用例,在获取 pdf 文件后,应用程序将获取 SFTP 服务器上具有相同名称的 CSV 格式的配置文件。 After fetching the config file, the application will process the original pdf file using the properties defined in the config file and upload it back to SFTP server using the outbound adapter.
获取配置文件后,应用程序将使用配置文件中定义的属性处理原始 pdf 文件,并使用出站适配器将其上传回 SFTP 服务器。
I am facing problems with fetching config files within the handler on the same thread using the outbound gateway.我在使用出站网关在同一线程上的处理程序中获取配置文件时遇到问题。
Here is my code:这是我的代码:
Register Integration Flows:注册集成流程:
for (String client : clientsArr) {
this.flowContext.registration(getInboundIntegrationFlow(client)).register();
}
this.flowContext.registration(getOutboundIntegrationFlow()).register();
this.flowContext.registration(sftpGatewayGetIntegrationFlow()).register();
Inbound Adapter Integration Flow:入站适配器集成流程:
@Autowired
private SftpPdfMessageHandler messageHandler;
private IntegrationFlow getInboundIntegrationFlow(String client) {
String remoteDirectory = getRemoteDirectory(client);
String localDirectory = getLocalDirectory(client);
String inboundAdapterId = getInboundAdapterId(client);
return IntegrationFlows
.from(Sftp.inboundAdapter(sftpSessionFactory())
.preserveTimestamp(true)
.remoteDirectory(remoteDirectory)
.autoCreateLocalDirectory(true)
.localDirectory(new File(localDirectory))
.maxFetchSize(Integer.parseInt(sftpProperties.getMaxFetchSize()))
.filter(new SftpSimplePatternFileListFilter(sftpProperties.getRemoteFileFilter()))
.deleteRemoteFiles(true),
e -> e.id(inboundAdapterId)
.autoStartup(true)
.poller(Pollers
.fixedDelay(Long.parseLong(sftpProperties.getPollPeriodInSeconds()), TimeUnit.SECONDS)
.receiveTimeout(Long.parseLong(sftpProperties.getPollerTimeout()))
.maxMessagesPerPoll(Long.parseLong(sftpProperties.getMaxMessagesPerPoll()))
))
.handle(inBoundHandler())
.get();
}
public MessageHandler inBoundHandler() {
return message -> {
File file = (File) message.getPayload();
messageHandler.handleMessage(file);
};
}
Outbound Adapter Integration Flow:出站适配器集成流程:
private IntegrationFlow getOutboundIntegrationFlow() {
return IntegrationFlows.from("sftpOutboundChannel")
.handle(Sftp.outboundAdapter(sftpSessionFactory(), FileExistsMode.FAIL)
.remoteDirectoryExpression(String.format("headers['%s']", FileHeaders.REMOTE_DIRECTORY))).get();
}
@Bean("sftpOutboundChannel")
public MessageChannel sftpOutboundChannel() {
return new DirectChannel();
}
SFTP Message Handler: SFTP 消息处理程序:
@Async("sftpHandlerAsyncExecutor")
public void handleMessage(File originalFile) {
File configFile = fetchConfigFile();
/*
process original file and store processed file in output file path on local directory
*/
boolean success = uploadFileToSftpServer(outputFilePath, client, entity);
if (success) {
deleteFileFromLocal(originalFile);
}
}
Outbound Gateway GET Integration Flow:出站网关 GET 集成流程:
private IntegrationFlow sftpGatewayGetIntegrationFlow() {
return IntegrationFlows.from("sftpGetInputChannel")
.handle(Sftp.outboundGateway(sftpSessionFactory(),
AbstractRemoteFileOutboundGateway.Command.GET, "payload")
.options(AbstractRemoteFileOutboundGateway.Option.DELETE,
AbstractRemoteFileOutboundGateway.Option.PRESERVE_TIMESTAMP)
.localDirectoryExpression(String.format("headers['%s']", Constants.HEADER_LOCAL_DIRECTORY_NAME))
.autoCreateLocalDirectory(true))
.channel("nullChannel")
.get();
}
@Bean("sftpGetInputChannel")
public MessageChannel sftpGetInputChannel() {
return new DirectChannel();
}
messageHandler.handleMessage()
method is called in async (with ThreadPoolTaskExecutor) which internally fetch config file using the outbound gateway. messageHandler.handleMessage()
方法在异步中调用(使用 ThreadPoolTaskExecutor),该方法使用出站网关在内部获取配置文件。 But I couldn't find a single channel where I can send and receive a message payload in the same thread.但是我找不到可以在同一个线程中发送和接收消息有效负载的单个通道。 I found MessagingTemplate in spring docs but couldn't find a way to connect this with my outbound gateway integration flow.
我在 spring 文档中找到了MessagingTemplate ,但找不到将其与我的出站网关集成流连接的方法。
sftpGetMessageTemplate.sendAndReceive(sftpGetInputChannel, new GenericMessage<>("/dir/file.csv", headers))
gives " Dispatcher has no subscribers for channel " exception with DirectChannel(). sftpGetMessageTemplate.sendAndReceive(sftpGetInputChannel, new GenericMessage<>("/dir/file.csv", headers))
通过 DirectChannel() 给出“ Dispatcher has no subscribers for channel ”异常。
I am looking for a solution where I can fetch required file from the server with any of the following ways:我正在寻找一种解决方案,我可以通过以下任何方式从服务器获取所需的文件:
Application needs to decide the directory path on runtime while using the GET command.
应用程序在使用 GET 命令时需要在运行时决定目录路径。
You probably need to learn what is a @MessagingGateway
and how to make it to interact with channels on your outbound gateway.您可能需要了解什么是
@MessagingGateway
以及如何使其与出站网关上的通道进行交互。
See docs for more info: https://docs.spring.io/spring-integration/docs/5.3.2.RELEASE/reference/html/messaging-endpoints.html#gateway有关更多信息,请参阅文档: https://docs.spring.io/spring-integration/docs/5.3.2.RELEASE/reference/html/messaging-endpoints.html#gateway
If you really would like to get a config file as a result, you should not do .channel("nullChannel")
.如果你真的想得到一个配置文件,你不应该这样做
.channel("nullChannel")
。 With the gateway in hands there is going to be replyChannel
header with a TemporaryReplyChannel
instance populated by the gateway.有了网关,
replyChannel
header 就会有一个由网关填充的TemporaryReplyChannel
实例。 Then in your code you just going to use that functional interface as an API to call.然后在您的代码中,您只需将该功能接口用作 API 来调用。
In fact that messaging gateway uses a mentioned MessagingTemplate.sendAndReceive()
.事实上,消息传递网关使用提到的
MessagingTemplate.sendAndReceive()
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.