How to differentiate SocketTimeoutException
So, here is my claim to fame. Here, we're walking down the StackTrace, looking for the origin-method of the Exception.
public class ExceptionOriginTracing {
public static void main(String[] args){
try {
originOne();
originTwo();
} catch (Exception e){
// Now for the magic:
for (StackTraceElement element : e.getStackTrace()){
if (element.getMethodName().equals("originOne")){
System.out.println("It's a read error!");
break;
} else if (element.getMethodName().equals("originTwo")){
System.out.println("It's a write error!");
break;
}
}
}
}
public static void originOne() throws Exception{
throw new Exception("Read Failed...", null);
}
public static void originTwo() throws Exception{
throw new Exception("Connect failed...", null);
}
}
The difference to parsing the message given by the Exception is, that a simple string is more likely to change, than the name of the actual method.
Aside from that, this is not an optimal solution! But sadly, there is no optimal solution here.
Also, with this approach, extra care must be taken when source obfuscation is used, which will change the method-names and therefor the return value of getMethodName()
.
The right way when designing something like this would be to wrap the exception in a new Exception, which provided methods to actually find out the real origin by using a flag or an enum.
Parsing a message/StackTrace always feels dirty and is subtable to break in future releases!
You can check Socket.isConnected. But since exceptions are thrown by different methods it is better to use two catch blocks with different actions.
try {
socket.connect(address);
} catch (SocketTimeoutException e) {
throw new SocketConnectionException(e);
}
try {
socket.getInputStream();
...
} catch (SocketTimeoutException e) {
throw new SocketReadException(e);
}
They come from different methods. 'Connection timed out' happens when calling connect(), implicitly or explicitly; 'read timed out' happens when calling read() or one of its cognates. So you can differentiate just be having two different catch blocks. But in either case you are probably going to close the connection ...