abautista
abautista

Reputation: 2780

How to protect variables outside of the try with resources statement?

Currently at my company we received Sonarqube reviews and in one of them, there's this warning about not using try-with-resources statement (see below):

public static void main(String[] args) throws Exception {

Socket s1 = null;
Socket s2 = null;
try {

    String host = InetAddress.getByName("myLocalHost").getHostAddress();
    int port = Integer.parseInt(System.getenv("Port");
    s1 = new Socket(host, port);
    s2 = new Socket(host2, port2);
   ... }
 ...}

The solution to this problem might look straightforward, that is, I can wrap the Socket variables inside the try () resources, but in order for doing this I need to declare the host and port variables outside of the try statement. My concern about this solution is that the variables that are outside of this try statement are now unprotected in case no host or port number is given.

public static void main(String[] args) throws Exception {

String host = InetAddress.getByName("myLocalHost").getHostAddress();
int port = Integer.parseInt(System.getenv("Port");

try (
    Socket s1 = new Socket(host, port);
    Socket s2 = new Socket(host2, port2);
    ) {
      ....
      }
   }

My question is if there's a better way to protect these variables that were left outside of the try statement or if the approach that I am following can be enough.

Upvotes: 0

Views: 87

Answers (1)

Holger
Holger

Reputation: 298233

You don’t need to connect immediately within the Socket’s constructor; you can create the instances first and connect later:

try(Socket s1 = new Socket(); Socket s2 = new Socket()) {

    InetAddress host = InetAddress.getByName("myLocalHost");
    int port = Integer.parseInt(System.getenv("Port"));
    s1.connect(new InetSocketAddress(host, port));

    InetAddress host2 = InetAddress.getByName("secondHost");
    int port2 = Integer.parseInt(System.getenv("Port2"));
    s2.connect(new InetSocketAddress(host2, port2));

    // use the Socket
}

There’s no problem in closing a Socket that never got connected, i.e. when an exception occurred after its creation but before the connect call.

Note that the code above uses the resolved InetAddress, instead of calling getHostAddress() to get a string that will be resolved again during the connect operation.

By removing this redundant operation, you could also write

try(Socket s1 = new Socket("myLocalHost",Integer.parseInt(System.getenv("Port")));
    Socket s2 = new Socket("secondHost", Integer.parseInt(System.getenv("Port2")))) {
    // use the Socket
}

This will resolve the name in the socket’s constructor in the first place. If an exception occurs, all resources that have been allocated so far, will be released.

Upvotes: 1

Related Questions