RequestHandlerRetryAdvice no se puede hacer que funcione con Ftp.outboundGateway en Spring Integration
Mi situación es similar a la descrita enesta pregunta SO. La diferencia es que no uso unaWebFlux.outboundGateway
pero unFtp.outboundGateway
en el que llamo unAbstractRemoteFileOutboundGateway.Command.GET
command, el problema común es que no puedo obtener la @ definiRequestHandlerRetryAdvice
para ser utilizado
La configuración se ve así (despojada a las partes relevantes):
@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;
}
}
El controlador está principalmente allí para fines de prueba, en la implementación real hay un sondeo. MiFtpProperties
mantenga una lista de servidores porque en la implementación real, uso unDelegatingSessionFactory
para elegir una instancia basada en algunos parámetros.
De acuerdo a Comentario de Gary Russell, Espero que se vuelva a intentar una descarga fallida. Pero si interrumpo una descarga del lado del servidor (al emitir "Kick user" en una instancia de FileZilla), solo obtengo un seguimiento inmediato de la pila y no vuelvo a intentarlo:
org.apache.commons.net.ftp.FTPConnectionClosedException: FTP response 421 received. Server closed connection.
[...]
También necesito subir archivos, para lo cual uso unFtp.outboundAdapter
. En este caso y con el mismoRetryTemplate
, si interrumpo una carga del lado del servidor, Spring Integration realiza dos intentos más con un retraso de 5 segundos cada uno, y solo luego registrajava.net.SocketException: Connection reset
, todo como se esperaba.
ntenté depurar un poco y noté eso justo antes del primer intento de subir a través deFtp.outboundAdapter
, un punto de quiebre enRequestHandlerRetryAdvice.doInvoke()
es golpeado. Pero al descargar a través deFtp.outboundGateway
, ese punto de quiebre esNunc golpear
Hay un problema con mi configuración, ¿podría alguien obtener elRequestHandlerRetryAdvice
trabajar conFtp.outboundGateway
/AbstractRemoteFileOutboundGateway.Command.GET
?