0
votes

I am trying to add a custom sftp component in Apache Camel to wrap the username, host, port and password in a configuration object to be passed to a sftpcomponent.

Below is the code that I have tried:

@Configuration
class SftpConfig {
    @Bean("sourceSftp")
    public SftpComponent getSourceSftpComponent(
            @Qualifier("sftpConfig")
            SftpConfiguration sftpConfig) throws Exception{
        SftpComponent sftpComponent = new SftpComponent();
        // not getting way to set the configuration
        return sftpComponent;
    }


    @Bean("sftpConfig")
    public SftpConfiguration getSftpConfig(
            @Value("${host}") String host,
            @Value("${port}") int port,
            @Value("${applicationUserName}") String applicationUserName,
            @Value("${password}") String password) {
        SftpConfiguration sftpConfiguration =  new SftpConfiguration();
        sftpConfiguration.setHost(host);
        sftpConfiguration.setPort(port);
        sftpConfiguration.setUsername(applicationUserName);
        sftpConfiguration.setPassword(password);
        return sftpConfiguration;
    }

}

//In other class

from("sourceSftp:<path of directory>") ---custom component

A similar approach in JMSComponent works fine where I have created a bean for sourcejms, but I am not able to do it for sftp as SftpComponent doesn't have set call for sftpconfiguration.

2

2 Answers

2
votes

The Camel maintainers seem to be moving away from providing individual components with a "setXXXConfiguration" method to configure their properties. The "approved" method of providing properties -- which works with the SFTP -- is to specify them on the connection URL:

from ("sftp://host:port/foo?username=foo&password=bar")
.to (....)

An alternative approach is to instantiate an endpoint and set its properties, and then use a reference to the endpoint in the from() call. There's a gazillion ways of configuring Camel -- this works for me for XML-based configuration:

<endpoint id="fred" uri="sftp://acme.net/test/">
  <property key="username" value="xxxxxxx"/>
  <property key="password" value="yyyyyyy"/>
</endpoint>
<route>
  <from uri="fred"/>
  <to uri="log:foo"/>
</route>
0
votes

You can customize it by extending the SftpComponent. This allows you to define multiple endpoints without providing the username/password for each endpoint definition.

Step 1: Extend SftpComponent and give your component a custom name, ie customSftp

@Component("customSftp")
public class CustomSftpComponent extends SftpComponent {

    private static final Logger LOG = LoggerFactory.getLogger(CustomSftpComponent.class);

    @Value("${sftp.username}")
    private String username;

    @Value("${sftp.password}")
    private String password;

    @SuppressWarnings("rawtypes")
    protected void afterPropertiesSet(GenericFileEndpoint<SftpRemoteFile> endpoint) throws Exception {
        SftpConfiguration config = (SftpConfiguration) endpoint.getConfiguration();
        config.setUsername(username);
        config.setPassword(password);
    }

}

Step 2: Create a camel route to poll 2 different folders using your custom component name.

@Component
public class PollSftpRoute extends RouteBuilder {

    @Override
    public void configure() throws Exception {

        from("{{sftp.endpoint1}}").routeId("pollSftpRoute1")
            .log(LoggingLevel.INFO, "Downloaded file from input folder 1.")
            .to("file:data/out1");

        from("{{sftp.endpoint2}}").routeId("pollSftpRoute2")
            .log(LoggingLevel.INFO, "Downloaded file from input folder 2.")
            .to("file:data/out2");

    }

}

Step 3: Place this in application.properties

camel.springboot.main-run-controller=true

sftp.endpoint1=customSftp://localhost.net/input/1?delay=30s
sftp.endpoint2=customSftp://localhost.net/input/2?delay=30s

sftp.username=sftp_user1_l
sftp.password=xxxxxxxxxxxx

With this you don't have to repeat the username/password for each endpoints.

Note: With this approach you wont be able to set the username/password in URI endpoint configuration. Anything you set in URI will be replaced in afterPropertiesSet.