nanosoft
nanosoft

Reputation: 3091

Getting session and SFTP channel in Java using JSch library

I am using JSch library for SFTP. I need to do several operations on SFTP server like move remote files in other directory, pull files, etc. For all these operations I need Session and from it I get Channel an then cast it to ChannelSftp. This is redundant step. So I thought of abstracting it into a private method.

private ChannelSftp getChannelSftp() throws JSchException
    {
        java.util.Properties config = new java.util.Properties();
        config.put("StrictHostKeyChecking", "no");
        JSch jsch = new JSch();
        Session session;
        session = jsch.getSession(VENDOR1_USERID, VENDOR1_SERVER, VENDOR1_PORT);
        session.setPassword(VENDOR1_PASSWORD);

        session.setConfig(config);
        session.connect();

        ChannelSftp channelSftp = null;

        Channel channel = session.openChannel("sftp");
        channel.connect();
        channelSftp = (ChannelSftp) channel;

        return channelSftp;
    }

But after the SFTP operation I need to disconnect from channel and session both. With above method, though I can disconnect from Channel in the calling method but I can't disconnect from Session as I don't have its instance which might be a leak so I now separated that into getSession() method and now ChannelSftp creation is duplicated in all methods.

What is better way to design/refactor it?

private Session getSession() throws JSchException
    {
        java.util.Properties config = new java.util.Properties();
        config.put("StrictHostKeyChecking", "no");
        JSch jsch = new JSch();
        Session session;
        session = jsch.getSession(VENDOR1_USERID, VENDOR1_SERVER, VENDOR1_PORT);
        session.setPassword(VENDOR1_PASSWORD);
        session.setConfig(config);
        session.connect();
        return session;
    }

Calling Method example: - Duplicated code indicated

public void sftp(File file) throws  SftpException, FileNotFoundException, JSchException
    {
        Session session = getSession();
/* Duplicate code START*/
        if ( session == null ) throw new SftpException(0 , "Service: Session is NULL"); 

        ChannelSftp channelSftp = null;

        Channel channel = session.openChannel("sftp");
        channel.connect();
        channelSftp = (ChannelSftp) channel;
/* Duplicate code END*/
        channelSftp.cd(VENDOR1_PATH);
        channelSftp.put(new FileInputStream(file), file.getName());

        channelSftp.disconnect();
        session.disconnect();
    }

Upvotes: 2

Views: 8853

Answers (1)

Martin Prikryl
Martin Prikryl

Reputation: 202222

If you use the SFTP session frequently enough, you should not recreate it for every operation. Opening an SSH/SFTP connection is very CPU demanding, both for the client and the server. It's quite a waste to shutdown a connection, if you are going to need a new one shortly.

So consider opening a single shared session and channel at the beginning of your "application" and reuse it for all operations.


To answer your actual session: I'd introduce another class that owns both Session and ChannelSftp (with methods like getSession() and getChannel()) and return that from the factory method.


Though actually, there's getSession method in the Channel class.

Upvotes: 3

Related Questions