nested IOException catch for socket close - java

I write to socket with:
OutputStream socketStream = socket.getOutputStream();
socketStream.write(buf);
But this can throw IOException, so I do:
try {
OutputStream socketStream = socket.getOutputStream();
socketStream.write(buf);
} catch (IOException e) {
// logging
} finally {
socket.close();
}
But socket.close also force me to catch IOException! So do I need try ... catch it again in finally?
When catch IOException from close, it mean socket not closed? So try close again? Or what to do?
Thanks

close() throws IOException because closing something usually implies calling flush(), and flushing might fail. For example, if you lose network connectivity and issue socket.close(), you cannot flush whatever you have buffered, so flush() will throw an exception. Because data might be lost, the exception is checked, so you are forced to deal with that possibility.
I think the best way to deal with this is:
try {
OutputStream socketStream = socket.getOutputStream();
socketStream.write(buf);
socket.close();
} catch (IOException e) {
// try to deal with your I/O error; do logging
} finally {
closeSilently(socket);
}
...
// Somewhere else, usually part of an utility JAR like Apache Commons IO
public static void closeSilently(Socket s) {
if (socket != null) {
try {
socket.close();
} catch (IOException e2) {
// do more logging if appropiate
}
}
}
This code will work normally in the common case. If something goes wrong (even inside close()), it will allow you to catch the exception and do something before unconditionally closing your socket and swallowing everything it might throw.

The Exception thrown by close can usually just be ignored (well you can log it). That's pretty much the same as throwing an exception in a destructor in C++ - there's not much (usually nothing) you can do about it and trying to close it again is nonsensical. Cleanup throwing exceptions is usually bad design - you can implement cleanup code for the cleanup but that's a recursive problem, in the end you'll just have to except that you can't handle it.

Related

How should I use IOException in `try-with-resources` nested in the method with`throws IOException` in the header?

AFAIK, the standard try-with-resources form
try(InputStream is= new ...){
... some reading from is
} catch (..){
... catching real problems
}
catch (IOException e) {
... if closing failed, do nothing - this clause is demanded by syntax
}
is equivalent to:
try{
InputStream is= new ...
... some reading from is
} catch (..){
... catching real problems
} finally {
try{
is.close();
} catch (IOException e) {
... if closing failed, do nothing
}
}
The first variant is more simple, of course. But I see the case when the second variant is absolutely OK, whereas the first becomes ununderstandable.
Imagine the situation, when you have got code, where the try(){} appears in the function with throws IOExceptions clause.
String readFromFile(...) throws IOException{
...
try(...){
...
}
}
The IOException in the second catch eats all IOExceptions, either connected to the attempt of closing or not. And does nothing. I suppose, that somewhere out of the method there is a piece of code that works with that IOException and does something noticeable. For example, logs the stack. So, local catches will be never reached. We are not interested in the second catch clause, but usually, we need some special reaction for the first one.
On the other hand, if we delete the closing catch(IOException e){} clause, counting on the throws in the method header, that absolutely uninteresting for us closing exception will be reacted to.
While we are catching the closing problems by IOException, I see no way out of the problem. And Eclipse java editor demands me to use this very exception for that clause!
How can I divide IOException appearing from closing from other IOExceptions, appearing in the try{} body?
I think Java is to blame for this one. The close() method should have thrown a different exception than IOException there is rarely anything the caller can do about it. Your only solution is to rewrap the IOExceptions you're interested in before rethrowing.
Usually what I do is I extract the entire content of the try-block to its own method where I can catch any IOExceptions and re-throw them as custom exceptions. I can then catch the remaining IOException by itself in the catch block.
public void foo() throws CustomException {
try (InputStream is= new ...) {
bar(is); //This catches internal IOExceptions and throws a CustomException
}
catch (IOException e) { //The close() exception
}
}

Use Try-With-Resources instead of finally block when multiple lines in try block throws exception

Code Snippet :
InputStream inputStream = null;
try{
ExternalServiceObject object = externalService.getObject();
inputStream = object.getInputStream();
// further uses of inputStream
} catch(Exception e){
throw e;
} finally {
if(inputStream != null)
inputStream.close();
}
Here, externalService.getObject() can also throw an exception.
Wish to refactor this code using try-with-resources, hence avoiding the finally block.
Or is the current behavior the most appropriate behavior.
All the comments and answers are appreciated.
If you don't need the external service object for anything else:
try (InputStream inputStream = externalService.getObject().getInputStream()) {
// further uses of inputStream
} catch (Exception e) {
// ... logging etc
throw e;
}
I believe that execution order in the try-with-resources is top-down
(like all other java variable definitions)
try
(
ExternalServiceObject externalServiceObject = externalService.getObject(),
InputStream inputStream = externalServiceObject.getInputStream();
)
{
// further uses of inputStream
}
catch (Exception e)
{
// do stuff.
}
Caveat: ExternalServiceObject must implement AutoCloseable
So, use try-with-resources if that's what you want to use:
try {
ExternalServiceObject object = externalService.getObject();
try (InputStream inputStream = object.getInputStream()) {
// ...
}
} catch (Exception e) {
throw e; // But why catch it only to rethrow?
}
The closing of the InputStream can be done using a try-with-resources block. It is more readable and less clunky. InputStream implements AutoCloseable and thus upon exiting a try-with-resources block the class's close method will automatically be called. If you are only using the InputStream for the scope of the try-catch-finally block then you should move it to the try block.
Also, you should avoid (where possible) catching Exception. Any resulting exceptions that are thrown in your try block could result in unwanted behavior.

Can closing a File fail?

I saw this code and wondered why in.close() was done in the finally block. The main point of try-with resources is that it closes the resources correct.
File file = new File(FILE_NAME);
FileInputStream in = null;
try (in = new FileInputStream(file)){
//do something
} catch (final FileNotFoundException e) {
log.log(Level.WARNING, "file not found, " + file.getAbsolutePath(), e);
} catch (final IOException e) {
log.log(Level.WARNING, "cannot access the file for reading", e);
} finally {
if (in != null){
try {
in.close();
} catch (final IOException e) {
log.log(Level.WARNING, "Attempt to close file failed.", e);
}
}
}
Will there be a situation where a file can be opened but cannot be closed using try-with-resources in Java?
The finally block in your example is redundant. The try-with-resources statement is basically doing the same (but is significantly less error prone!). As it is executed after the try-with-resources statement attempts to close the resources, the finally block is essentially a noop (there may be the possibility of a second attempt to close a resource succeeding after the first fails - but if this is even possible, it is a negligible edge case and certainly non-deterministic).
Note that the catch blocks in contrast are significant. The attempt to close resources will take place before a catch block is activated, leading to the possibility that more than one exception occurs. This is solved by using suppressed exceptions. Therefore, if using the resource fails, there will nonetheless be an attempt to close it properly (which will often fail too) and catch blocks will receive the first (most likely root) cause, instead of the exception thrown while closing hiding the first error.
For more informations see the official documentation!
This is not exclusive to files, it happens in general with I/O.
The Java API specs that the close() method of InputStream may launch an exception if "An I/O error occurs"
So yes, it can happen, that behaviour generates that funny (or not so funnty) try-catch-finally-try-catch blocks.
I would do a simple test with some removable storage (USB stick, for instance):
Just write a program that opens a FileInputStream with a file from the USB stick and then prompts "Please remove the storage device", waits for an <Enter> and then tries in.close(). I would bet some IOException would be thrown.
Yes, this can happen. The method signature for close() does throw an IOException, so a good programmer should be prepared for this eventuality.
Often, the catch block will be moved outside the method, which makes handling it somewhat easier and cleaner looking. For example:
public static void main(String[] args)
{
try {
readFile(new File("MyFile.txt"));
} catch (IOException e) {
/* handle the exception */
}
}
private static void readFile(File file) throws IOException
{
FileInputStream in = null;
try {
in = new FileInputStream(file);
/* Read the file. THIS MIGHT FAIL! */
} finally {
if (in != null) /* Check this because new FileInputStream() could have failed */
in.close(); /* If this throws and exception, it will be handled by main() */
}
}

What is the proper way to disconnect from an FTP server using SimpleFTP?

Very new to Java in particular, using the SimpleFTP library to send a file to a server.
It seems like any method call on a SimpleFTP object seems to require being inclosed in a try-catch. What is the proper way to disconnect from the server, then?
For example:
private void ftp()
{
int portNumber = 21;
SimpleFTP ftp = new SimpleFTP();
try
{
ftp.connect("serverAddress", portNumber, "userName", "password");
ftp.bin();
ftp.cwd("dir");
ftp.stor(new File("filePath"));
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
ftp.disconnect();
}
}
This does not compile, because of the content in fianlly's body. If I move it up to the try block and scrap the finally, it'll compile... But what if my app connects to the server, then throws an exception while doing the other tasks?
What you didn't mention is that the reason you're having a problem is that disconnect() is also declared to throw an IOException.
Looking at the source for SimpleFTP you find:
public synchronized void disconnect() throws IOException {
try {
sendLine("QUIT");
}
finally {
socket = null;
}
}
All it's doing is sending the QUIT command to the remote FTP server then just dropping the reference to the socket in its finally block. If that throws .... it means the socket is already dead, but since you're disconnecting you really don't care (If I'd written that client, i'd have caught and ignored the exception for that reason and not had it throw).
In your finally block just wrap it in it's own try/catch block and don't do anything in the catch block. Option B is just putting it in the try block. The only reason it's going to throw is if the socket is already disconnected and letting the SimpleFTP instance fall out of scope after an exception will clean things up just as well.
Surround the disconnect call with its' own try catch block...
finally
{
if (ftp != null) {
try {
ftp.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
}

Closing a Java FileInputStream

Alright, I have been doing the following (variable names have been changed):
FileInputStream fis = null;
try
{
fis = new FileInputStream(file);
... process ...
}
catch (IOException e)
{
... handle error ...
}
finally
{
if (fis != null)
fis.close();
}
Recently, I started using FindBugs, which suggests that I am not properly closing streams. I decide to see if there's anything that can be done with a finally{} block, and then I see, oh yeah, close() can throw IOException. What are people supposed to do here? The Java libraries throw too many checked exceptions.
For Java 7 and above try-with-resources should be used:
try (InputStream in = new FileInputStream(file)) {
// TODO: work
} catch (IOException e) {
// TODO: handle error
}
If you're stuck on Java 6 or below...
This pattern avoids mucking around with null:
try {
InputStream in = new FileInputStream(file);
try {
// TODO: work
} finally {
in.close();
}
} catch (IOException e) {
// TODO: error handling
}
For a more detail on how to effectively deal with close, read this blog post: Java: how not to make a mess of stream handling. It has more sample code, more depth and covers the pitfalls of wrapping close in a catch block.
Something like the following should do it, up to you whether you throw or swallow the IOException on attempting to close the stream.
FileInputStream fis = null;
try
{
fis = new FileInputStream(file);
... process ...
}
catch (IOException e)
{
... blah blah blah ...
}
finally
{
try
{
if (fis != null)
fis.close();
}
catch (IOException e)
{
}
}
You could use the try-with-resources feature added JDK7. It was created precisely to deal with this kind of things
static String readFirstLineFromFile(String path) throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
}
}
The documenation says:
The try-with-resources statement ensures that each resource is closed
at the end of the statement.
You could also use a simple static Helper Method:
public static void closeQuietly(InputStream s) {
if (null == s) {
return;
}
try {
s.close();
} catch (IOException ioe) {
//ignore exception
}
}
and use this from your finally block.
Nothing much to add, except for a very minor stylistic suggestion. The canonical example of self documenting code applies in this case - give a descriptive variable name to the ignored IOException that you must catch on close().
So squiddle's answer becomes:
public static void closeQuietly(InputStream s) {
try {
s.close();
} catch (IOException ignored) {
}
}
In most cases, I find it is just better not to catch the IO exceptions, and simply use try-finally:
final InputStream is = ... // (assuming some construction that can't return null)
try {
// process is
...
} finally {
is.close();
}
Except for FileNotFoundException, you generally can't "work around" an IOException. The only thing left to do is report an error, and you will typically handle that further up the call stack, so I find it better to propagate the exception.
Since IOException is a checked exception, you will have to declare that this code (and any of its clients) throws IOException. That might be too noisy, or you might not want to reveal the implementation detail of using IO. In that case, you can wrap the entire block with an exception handler that wraps the IOException in a RuntimeException or an abstract exception type.
Detail: I am aware that the above code swallows any exception from the try block when the close operation in the finally block produces an IOException. I don't think that is a big problem: generally, the exception from the try block will be the same IOException that causes the close to fail (i.e. it is quite rare for IO to work fine and then fail at the point of closing). If this is a concern, it might be worth the trouble to "silence" the close.
The following solution correctly throws an exception if close fails without hiding a possible exception before the close.
try {
InputStream in = new FileInputStream(file);
try {
// work
in.close();
} finally {
Closeables.closeQuietly(in);
}
} catch(IOException exc) {
// kernel panic
}
This works because calling close a second time has no effect.
This relies on guava Closeables, but one can write its own closeQuietly method if preferred, as shown by squiddle (see also serg10).
Reporting a close error, in the general case, is important because close might write some final bytes to the stream, e.g. because of buffering. Hence, your user wants to know if it failed, or you probably want to act somehow. Granted, this might not be true in the specific case of a FileInputStream, I don't know (but for reasons already mentioned I think it is better to report a close error if it occurs anyway).
The above code is a bit difficult to grasp because of the structure of the embedded try blocks. It might be considered clearer with two methods, one that throws an IOException and one that catches it. At least that is what I would opt for.
private void work() throws IOException {
InputStream in = new FileInputStream(file);
try {
// work
in.close();
} finally {
Closeables.closeQuietly(in);
}
}
public void workAndDealWithException() {
try {
work();
} catch(IOException exc) {
// kernel panic
}
}
Based on http://illegalargumentexception.blogspot.com/2008/10/java-how-not-to-make-mess-of-stream.html (referenced by McDowell).
Hopefully we will get closures in Java some day, and then we will lose lots of the verbosity.
So instead there will be a helper method somwhere in javaIO that you can import, it will probably takes a "Closable" interface and also a block. Inside that helper method the try {closable.close() } catch (IOException ex){ //blah} is defined once and for all, and then you will be able to write
Inputstream s = ....;
withClosable(s) {
//your code here
}
Are you concerned primarily with getting a clean report from FindBugs or with having code that works? These are not necessarily the same thing. Your original code is fine (although I would get rid of the redundant if (fis != null) check since an OutOfMemoryException would have been thrown otherwise). FileInputStream has a finalizer method which will close the stream for you in the unlikely event that you actually receive an IOException in your processing. It's simply not worth the bother of making your code more sophisticated to avoid the extremely unlikely scenario of
you get an IOException and
this happens so often that you start to run into finalizer backlog issues.
Edit: if you are getting so many IOExceptions that you are running into problems with the finalizer queue then you have far far bigger fish to fry! This is about getting a sense of perspective.

Categories