Фантастика, ты спас мой день, спасибо огромное! Будучи новичком в Spring в целом и в Spring Integration в частности, я бы никогда не нашел такой причины и решения.
итуация похожа на описанную вэтот ТАК вопрос, Разница в том, что я не используюWebFlux.outboundGateway
ноFtp.outboundGateway
на котором я называюAbstractRemoteFileOutboundGateway.Command.GET
команда, общая проблема в том, что я не могу получить определенныйRequestHandlerRetryAdvice
использоваться.
Конфигурация выглядит следующим образом (разделена на соответствующие части):
@RestController
@RequestMapping( value = "/somepath" )
public class DownloadController
{
private DownloadGateway downloadGateway;
public DownloadController( DownloadGateway downloadGateway )
{
this.downloadGateway = downloadGateway;
}
@PostMapping( "/downloads" )
public void download( @RequestParam( "filename" ) String filename )
{
Map<String, Object> headers = new HashMap<>();
downloadGateway.triggerDownload( filename, headers );
}
}
@MessagingGateway
public interface DownloadGateway
{
@Gateway( requestChannel = "downloadFiles.input" )
void triggerDownload( Object value, Map<String, Object> headers );
}
@Configuration
@EnableIntegration
public class FtpDefinition
{
private FtpProperties ftpProperties;
public FtpDefinition( FtpProperties ftpProperties )
{
this.ftpProperties = ftpProperties;
}
@Bean
public DirectChannel gatewayDownloadsOutputChannel()
{
return new DirectChannel();
}
@Bean
public IntegrationFlow downloadFiles( RemoteFileOutboundGatewaySpec<FTPFile, FtpOutboundGatewaySpec> getRemoteFile )
{
return f -> f.handle( getRemoteFile, getRetryAdvice() )
.channel( "gatewayDownloadsOutputChannel" );
}
private Consumer<GenericEndpointSpec<AbstractRemoteFileOutboundGateway<FTPFile>>> getRetryAdvice()
{
return e -> e.advice( ( (Supplier<RequestHandlerRetryAdvice>) () -> {
RequestHandlerRetryAdvice advice = new RequestHandlerRetryAdvice();
advice.setRetryTemplate( getRetryTemplate() );
return advice;
} ).get() );
}
private RetryTemplate getRetryTemplate()
{
RetryTemplate result = new RetryTemplate();
FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy();
backOffPolicy.setBackOffPeriod( 5000 );
result.setBackOffPolicy( backOffPolicy );
return result;
}
@Bean
public RemoteFileOutboundGatewaySpec<FTPFile, FtpOutboundGatewaySpec> getRemoteFile( SessionFactory sessionFactory )
{
return
Ftp.outboundGateway( sessionFactory,
AbstractRemoteFileOutboundGateway.Command.GET,
"payload" )
.fileExistsMode( FileExistsMode.REPLACE )
.localDirectoryExpression( "'" + ftpProperties.getLocalDir() + "'" )
.autoCreateLocalDirectory( true );
}
@Bean
public SessionFactory<FTPFile> ftpSessionFactory()
{
DefaultFtpSessionFactory sessionFactory = new DefaultFtpSessionFactory();
sessionFactory.setHost( ftpProperties.getServers().get( 0 ).getHost() );
sessionFactory.setPort( ftpProperties.getServers().get( 0 ).getPort() );
sessionFactory.setUsername( ftpProperties.getServers().get( 0 ).getUser() );
sessionFactory.setPassword( ftpProperties.getServers().get( 0 ).getPassword() );
return sessionFactory;
}
}
@SpringBootApplication
@EnableIntegration
@IntegrationComponentScan
public class FtpTestApplication {
public static void main(String[] args) {
SpringApplication.run( FtpTestApplication.class, args );
}
}
@Configuration
@PropertySource( "classpath:ftp.properties" )
@ConfigurationProperties( prefix = "ftp" )
@Data
public class FtpProperties
{
@NotNull
private String localDir;
@NotNull
private List<Server> servers;
@Data
public static class Server
{
@NotNull
private String host;
@NotNull
private int port;
@NotNull
private String user;
@NotNull
private String password;
}
}
Контроллер в основном используется только для тестирования, в реальной реализации есть модуль опроса. мойFtpProperties
держать список серверов, потому что в реальной реализации я используюDelegatingSessionFactory
выбрать экземпляр на основе некоторых параметров.
Согласно сКомментарий Гари РасселаЯ ожидаю повторной попытки неудачной загрузки. Но если я прерву загрузку на стороне сервера (введя «Kick user» в экземпляре FileZilla), я просто получу немедленную трассировку стека и никаких повторных попыток:
org.apache.commons.net.ftp.FTPConnectionClosedException: FTP response 421 received. Server closed connection.
[...]
Мне также нужно загрузить файлы, для которых я используюFtp.outboundAdapter
, В этом случае и с тем жеRetryTemplate
Если я прерву загрузку на стороне сервера, Spring Integration выполнит еще две попытки с задержкой в 5 с каждая, и только после этого регистрируетсяjava.net.SocketException: Connection reset
все как положено.
Я попытался немного отладить и заметил, что перед первой попыткой загрузить черезFtp.outboundAdapter
, точка останова наRequestHandlerRetryAdvice.doInvoke()
ударил Но при загрузке черезFtp.outboundGateway
эта точка останованикогда ударил.
Есть ли проблема с моей конфигурацией, кто-то может получитьRequestHandlerRetryAdvice
работать сFtp.outboundGateway
/AbstractRemoteFileOutboundGateway.Command.GET
?