Question

I'm writing an application which uses sshj library for SSH connections. User opens Connect Dialog from menu, types login data and clicks Connect button to establish a connection. Then the user performs various operations from different panels and frames. My question is: where should I keep this connection to make it available to every panel and frame that needs it until the user clicks Disconnect button? I thought about static field in some custom class but I'm not convinced to do so. What are your ideas?

Was it helpful?

Solution

It sounds like you are interested in some type of pool.

You can do this in different ways. One way is to have a class that handles all the connections, which is a singleton, sort of. Then you simply ask the pool for a connection, for instance

SSHConnection con = ConnectionPool.getConnection(host, port);

You could also use a proxy for this. In a proxy, you actually get a placeholder instead of the actual connection. The proxy shares information with other instances, sort of like

class ConnectionProxy {
    private static SSHConnection connection;
}

the connection variable is shared, and when you create a new ConnectionProxy, you will actually get the old connection, but it looks like you get a new connection.

Another option is to simply pass the instance around to all classes that needs it. This will allow you to keep track of who does what, but you will loose the flexibility of getting a connection from wherever you want.

Passing an instance around will help if you are debugging though, think of it like this. You are in a crowded room and you have a some money laying in a box that needs a key to open. If you hand that key to one person (the class that needs it) and leave the room and come back and the money is gone, you can blame that person. If instead you just leave the key on the table next to the box (the instance is global) and leave the room, come back and the money is gone, then good luck finding out who took it.

References:
*] Proxy pattern - WikiPedia


Proxy example

More specifically, it could look something like this:

public class ConnectionProxy implements Connectable {

    // where Connectable is some shared interface between ConnectionProxy
    // and SSHConnection. The proxy should "look like" a connection, it just
    // hides the actual connection behind the scenes.

    private static SSHConnection connection;

    public ConnectionProxy() { }

    public ConnectionProxy(String host, int port) {
        connection = new SSHConnection(host, port);
    }

    public void connect(String host, int port) {
        if (isConnected()) {
            return;
        }
        connection = new SSHConnection(host, port);
    }

    public void reconnect() {
        connection = new SSHConnection(connection.getHost(), connection.getPort());
    }

    public boolean isConnected() {
        return connection != null && connection.isConnected();
    }
}

You use the class by either instantiating it or connecting it.

class Program {
    public void sendMessage() {
        ConnectionProxy proxy = new ConnectionProxy();
        if (!proxy.isConnected()) {
            // I guess noone connected it
            return;
        }
        proxy.sendBytes();
    }
 }

And in your connection dialog you instantiate or connect the ConnectionProxy. You could add support for several connections, i.e. different hosts and ports, just by making the variable connection a list instead, and checking the host and port for the right connection. You basically create a pool of connections, but to the client class it looks like it is creating the connection.

OTHER TIPS

Doesn't matter where you put it, so long as you provide a getter method for retrieving it, and that getting method is public.

I think it's more a question of where it logically belongs. If it's a property of the application (as opposed to a window, frame, profile, whatever) put the getter in the main application class.

Design-wise, I'd recommend wrapping the operations you can perform over SSH in a separate class (RemoteCommands or some such), and injecting (setting as a property) an instance of this class everywhere you need to perform a remote command from.

If this seems like a lot of extra boilerplate code because every single frame and panel needs it, this shouldn't say "I need a global variable" to you. It should say "I should reduce the number of components that directly execute remote commands".

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top