How to call SFTP Outbound Gateway operations in Configuration from Component in Spring

1k Views Asked by At

I have looked here here and am unable to get listFiles to work:

    @Bean
    public SessionFactory<LsEntry> sftpSessionFactory() {
        DefaultSftpSessionFactory factory = new DefaultSftpSessionFactory(true);
        factory.setHost("localhost");
        factory.setPort(port);
        factory.setUser("foo");
        factory.setPassword("foo");
        factory.setAllowUnknownKeys(true);
        factory.setTestSession(true);
        return new CachingSessionFactory<LsEntry>(factory);
    }

    @MessagingGateway
    public interface MyGateway {
         @Gateway(requestChannel = "sftpChannel")
         List<File> listFiles();

    }
    @Bean
    @ServiceActivator(inputChannel = "sftpChannel")
    public MessageHandler handler() {
        return new SftpOutboundGateway(ftpSessionFactory(), "ls", "'my_remote_dir/'");
    }

where in my @Component class I have this:

    @Autowired
    MyGateway gateway;

    public void list(){
        List<File> files = gateway.listFiles();
    }

when I run this, I get an error receive is not supported, because no pollable reply channel has been configured

I assume this is an issue with my knowledge/understanding of integration channels. Perhaps I am missing a bean, but my main goal here is to do replace my current use of the inboundchannel adapter to request files ad hoc instead of continuously polling the fileserver

2

There are 2 best solutions below

0
On BEST ANSWER

Yes, the story mentioned in the Spring Integration Gateway with no arguments is definitely related to your problem.

You are missing the fact that List<File> listFiles() contract comes without arguments, so it is not clear for the framework what to use for sending to that sftpChannel. Therefore it try to call receive. But since your sftpChannel is not PollableChannel, you got that error. Anyway that is a different story and not what you want to get as a reply from sending a message to the sftpChannel as you try to do with that gateway contract.

You just need to be more explicit and say what to use as a payload for that no-arg gateway contract.

See more info in docs: https://docs.spring.io/spring-integration/docs/current/reference/html/messaging-endpoints.html#gateway-calling-no-argument-methods. The @Payload is an answer for you. Or you can specify a payloadExpression on that @Gateway annotation or a defaultPayloadExpression on the @MessagingGateway.

0
On

Maybe it is too late, but you also could change your no-arg gateway contract to a one-arg contract having nothing to annotate additionally.

@MessagingGateway
public interface MyGateway {
     @Gateway(requestChannel = "sftpChannel")
     List<File> listFiles(String remoteDir);

}

@Bean
@ServiceActivator(inputChannel = "sftpChannel")
public MessageHandler handler() {
    return new SftpOutboundGateway(ftpSessionFactory(), Command.LS, "payload");
}

In your @Component class then you will have:

@Autowired
MyGateway gateway;

public void list(){
    List<File> files = gateway.listFiles("'my_remote_dir/'");
}