2

my application.properties file look like this:

sftp.host=0.0.0.0
sftp.port=22
sftp.user=foo
sftp.password=pass

and my upload class with upload method looks like this:

public class UpAndDownLoad {

  @Value("${sftp.host}")
  private String sftpHost;
  @Value("${sftp.port}")
  private int sftpPort;
  @Value("${sftp.user}")
  private String sftpUser;
  @Value("${sftp.password}")
  private String sftpPasword;

  private DefaultSftpSessionFactory getSftpFactory() {
    DefaultSftpSessionFactory factory = new DefaultSftpSessionFactory();
    factory.setHost(sftpHost);
    factory.setPort(sftpPort);
    factory.setAllowUnknownKeys(true);
    factory.setUser(sftpUser);
    factory.setPassword(sftpPasword);
    return factory;
  }

  public void upload() throws IOException {
    SftpSession session = getSftpFactory().getSession();
    InputStream resourceAsStream = UpAndDownLoad.class.getClassLoader().getResourceAsStream("mytextfile.txt");
    session.write(resourceAsStream, "upload/mynewfile" + LocalDateTime.now() + ".txt");
    session.close();
  }

Whenever I type out the values of sftp host, user, password the upload method works meticulously.

  private DefaultSftpSessionFactory getSftpFactory() {
    DefaultSftpSessionFactory factory = new DefaultSftpSessionFactory();
    factory.setHost("0.0.0.0");
    factory.setPort(22);
    factory.setAllowUnknownKeys(true);
    factory.setUser("foo");
    factory.setPassword("passs");
    return factory;
  }

But as soon as i pass in the vlaues from the application properties, like shown at the second code block, it fails with: java.lang.IllegalStateException: failed to create SFTP Session

robinhoodjr
  • 415
  • 8
  • 20
  • 2
    You don't show how you're creating your `UpAndDownLoad` instance, but it's likely your instance isn't Spring-managed. Convert to using constructor injection (you can use `@Value` on constructor parameters, and using `@ConfigurationProperties` is even better) and see if that doesn't show where your problem is. – chrylis -cautiouslyoptimistic- Mar 19 '20 at 05:50

2 Answers2

1

Simply you modify your applicationContext.xml by this adding <context:property-holder>.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

       <context:property-placeholder location="classpath:application.properties"/>

</beans>

or if Java based Config, then this :

@Configuration
@PropertySource("classpath:application.properties")
public class Config {

}

Make the class as component.

@Component
public class UpAndDownLoad {

  @Value("${sftp.host}")
  private String sftpHost;
  @Value("${sftp.port}")
  private int sftpPort;
  @Value("${sftp.user}")
  private String sftpUser;
  @Value("${sftp.password}")
  private String sftpPasword;

  private DefaultSftpSessionFactory getSftpFactory() {
    DefaultSftpSessionFactory factory = new DefaultSftpSessionFactory();
    factory.setHost(sftpHost);
    factory.setPort(sftpPort);
    factory.setAllowUnknownKeys(true);
    factory.setUser(sftpUser);
    factory.setPassword(sftpPasword);
    return factory;
  }

  public void upload() throws IOException {
    SftpSession session = getSftpFactory().getSession();
    InputStream resourceAsStream = UpAndDownLoad.class.getClassLoader().getResourceAsStream("mytextfile.txt");
    session.write(resourceAsStream, "upload/mynewfile" + LocalDateTime.now() + ".txt");
    session.close();
  }

}
Anish B.
  • 9,111
  • 3
  • 21
  • 41
  • 1
    It was helpful. but, it fails with `java.lang.IllegalStateException: failed to create SFTP Session` at line `SftpSession session = getSftpFactory().getSession();` – robinhoodjr Mar 19 '20 at 13:55
  • @robinhoodjr Have you debugged the code ? If not, plz debug. Check whether are you able to get into `getSftpFactory()` method or not. – Anish B. Mar 19 '20 at 14:14
  • @robinhoodjr Also, write a small main method where you write a code to take session and check whether you are able to take session from machine `0.0.0.0:22` having user as `foo` and password as `pass`. – Anish B. Mar 19 '20 at 14:18
  • 1
    i am able to conenct to 0.0.0.0:22 from a terminal with the user foo and password pass – robinhoodjr Mar 19 '20 at 15:12
1

If you want @Value annotations to work you should make this object spring managed. add @Component on it and @Autowire

better way is to create separate SftpProperties as @ConfigurationProperties

@Component
@ConfigurationProperties("sftp")
public class SftpProperties {

    private String host;
    private int port;
    private String user;
    private String password;

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public String getUser() {
        return user;
    }

    public void setUser(String user) {
        this.user = user;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }


    @Override
    public String toString() {
        return "SftpProperties{" +
                "host='" + host + '\'' +
                ", port=" + port +
                ", user='" + user + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

And you will have more declarative configuration and auto completion into your application.properties

@Component
public class UpAndDownLoad {

    final
    SftpProperties props;

   @Autowired
    public UpAndDownLoad(SftpProperties props) {
        this.props = props;
    }
    private DefaultSftpSessionFactory getSftpFactory() {
        DefaultSftpSessionFactory factory = new DefaultSftpSessionFactory();
        factory.setHost(props.getHost());
        factory.setPort(props.getPort());
        factory.setAllowUnknownKeys(true);
        factory.setUser(props.getUser());
        factory.setPassword(props.getPassword());
        return factory;
    }

    public void upload() throws IOException {
        SftpSession session = getSftpFactory().getSession();
        InputStream resourceAsStream = UpAndDownLoad.class.getClassLoader().getResourceAsStream("mytextfile.txt");
        session.write(resourceAsStream, "upload/mynewfile" + LocalDateTime.now() + ".txt");
        session.close();
    }
}
Nonika
  • 2,490
  • 13
  • 15
  • It was helpful. but, it fails with `java.lang.IllegalStateException: failed to create SFTP Session` at line `SftpSession session = getSftpFactory().getSession();` – robinhoodjr Mar 19 '20 at 14:03
  • This is entirely different issue. can you werify that SftpProperties is filled with correct values from application.properties. maybe with `System.out.println(props)` in `getSftpFactory` somewhere – Nonika Mar 19 '20 at 14:34
  • it shows the right props and the credentials can be used from a terminal to establish a connxn – robinhoodjr Mar 19 '20 at 15:14
  • Can you post full stack trace of your error. given the credentials are correct this should give us clue whats happening – Nonika Mar 19 '20 at 15:19
  • 1
    it worked. Your solution is correct and descriptive as well. But the other solution is also correct. I wish i could flag both as answers. – robinhoodjr Mar 19 '20 at 15:37
  • 1
    but it didn't run unless i add a config class as mentioned by Anish B. below in this same post. – robinhoodjr Mar 19 '20 at 16:29