0
votes

I need to upload an image to FTP server. So I've created integration configuration with SessionFactory, MessageHandler, and MessageGateway for uploading files to FTP server:

@Configuration
@IntegrationComponentScan
public class FtpConfiguration {

    @Bean
    public SessionFactory<FTPFile> ftpSessionFactory() {
        DefaultFtpSessionFactory defaultFtpSessionFactory = new DefaultFtpSessionFactory();
        //setup
        return new CachingSessionFactory<>(defaultFtpSessionFactory);
    }

    @Bean
    @ServiceActivator(inputChannel = "toFtpChannel")
    public MessageHandler handler() {
        FtpMessageHandler handler = new FtpMessageHandler(ftpSessionFactory());
        handler.setAutoCreateDirectory(true);
        handler.setRemoteDirectoryExpression(new LiteralExpression(""));
        handler.setFileNameGenerator(message -> (String) message.getHeaders().get("filename"));
        return handler;
    }

    //to show you that I've tried both
    /*@Bean
    public IntegrationFlow ftpOutboundFlow() {
        return IntegrationFlows.from("toFtpChannel")
                .handle(Ftp.outboundAdapter(ftpSessionFactory(), FileExistsMode.REPLACE)
                        .useTemporaryFileName(false)
                        .fileNameExpression("headers['" + FileHeaders.FILENAME + "']")
                        .remoteDirectory("")
                ).get();
    }*/

    @MessagingGateway
    public interface UploadGateway {

        @Gateway(requestChannel = "toFtpChannel")
        void upload(@Payload byte[] file, @Header("filename") String filename, @Header("path") String path);
    }

}

Successfully build an application. And then I'm trying to upload some file:

@Autowired
UploadGateway uploadGateway;


@Override
public void uploadImage(byte[] scanBytes, String filename, String path) {
    try {
        uploadGateway.upload(scanBytes, filename, path);
    } catch (Exception e) {
        log.error("WRONG", e);
    }
}

And then it says: "No bean named 'toFtpChannel' available" I've tried nearly every tutorial, what do I do wrong?

dependencies:

 <dependency>
        <groupId>org.springframework.integration</groupId>
        <artifactId>spring-integration-file</artifactId>
        <version>RELEASE</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-integration</artifactId>
        <version>RELEASE</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.integration</groupId>
        <artifactId>spring-integration-ftp</artifactId>
        <version>RELEASE</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.integration</groupId>
        <artifactId>spring-integration-java-dsl</artifactId>
        <version>RELEASE</version>
    </dependency>
3

3 Answers

0
votes

Request channel should exists actually before you can refer it in your annotation. Declare channel and that issue should be gone

@Bean
public MessageChannel toFtpChannel() {
    return new DirectChannel();
}

This example creates DirectChannel but you can choose any implementation according your semantic.

Hope it helps!

0
votes

Dosn't look like your application is really Spring Boot: we don't see a @SpringBootApplication annotation. Exactly this one will kick the proper auto-configuration, including one for Spring Integration.

If you still don't care about Spring Boot there, then you are missing a standard @EnableIntegration annotation: https://docs.spring.io/spring-integration/docs/current/reference/html/overview.html#configuration-enable-integration

0
votes

@Sergey Prokofiev 's answer solved here, but I want to point out a weird thing.

I had a
@Gateway(requestChannel = "json.event.deserialize.input")
And the bean below didn't work:

    @Bean
    public MessageChannel jsonEventDeserializeInput() {
        return MessageChannels.direct("json.event.deserialize.input").get();
    }

After I changed the gateway to
@Gateway(requestChannel = "jsonEventDeserializeInput")
It did work.

So, even though the documentation says that id(...) is Used as the beanName to register the bean in the application context for this component., it didn't find any bean with name equal to the value that I passed to id(...).