How to catch exceptions from try-with-resources?

Viewed 1106

Though the try-with-resources feature handles all the functionalities for AutoClosable objects itself, but there are some specific cases I have faced in my recent project.

I was reading a file using:

try(InputStream stream = loader.getResourceAsStream("remote-config.xml"))

The issue was that the path from where I am reading the file above was wrong. So, I expected an exception as 'FileNotFoundException'. Now, I know that I can have catch block in place and not have it in place as well when I am using try-with-resources. Also, to my surprise, the catch block I had did not catch any exception and I did not get any error in my logs.

If there is no need of that catch block with try-with-resources, then why can it be added there? And, when it is not there, are there any exceptions thrown? Are the exceptions thrown to the JVM in the second case and how can I log those?

Below is the code I have:

    private Map<String, String> fillMappingsMap(Map<String, String> serviceToJndiNameMappings)
    {
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        try(InputStream stream = loader.getResourceAsStream("remoting-config.xml"))
        {
            if (stream != null)
            {
                // logic for - read the file , fill the map to be returned.
            }
        }
        catch (IOException | ParserConfigurationException | SAXException e)
        {
            logger.error("Could not create service to JNDI Name mapping.", e);
        }
        return serviceToJndiNameMappings;
    }
3 Answers

If there is no need of that catch block with try-with-resources, then why can it be added there?

If there is no need for training wheels on a bicycle, why can they be added?

Answer: because sometimes there is a need, and sometimes there isn't a need.

In your example, if you need to handle an exception emanating from a try with resources, then you can add a catch to handle it. (And you can even add a finally if you need to.)

(And for what it is worth, you don't have to have a catch on a classic try ... statement. You could just have a finally.)


And, when it is not there, are there any exceptions thrown?

There can be. It depends on what try does.


Are the exceptions thrown to the JVM in the second case ...

Exceptions are not thrown "to the JVM". That doesn't make sense.

But if you are asking if exceptions might be thrown, then yes, they might be. There maybe unchecked exceptions thrown by code in the try block; e.g. code that you indicated by the "// ... fill the map to be returned logic." comment.

For example ... if there was an NPE bug, or if you filled up the heap while filling the map and got an OOME.


... and how can I log those?

I doubt that it is a good idea to log exceptions there. But you could do it by catching them, logging them and then rethrowing them.

Same as if you were logging exceptions normally ...


You seem to be worried by this:

... I am going to miss a very important exception i.e. FileNotFoundException which can make anyone irritated.

You are not going to miss it:

  1. FileNotFoundException is a subclass of IOException so you are definitely catching it when you catch IOException.

  2. Even if you weren't catching IOException, FileNotFoundException is a checked exception. That means that the Java compiler will insist that you either catch it, or declare it in a "throws" clause in the enclosing method.

  3. Finally loader.getResourceAsStream("remote-config.xml") will not throw FileNotFoundException anyway! It is not opening a file. It is acquiring an input stream for a resource. If it can't find the resource, the getResourceAsStream call returns null rather than throwing an exception.

I recommend that you read the Catch or Specify page from the Oracle Java Tutorial. It will answer a lot of your confusion about Java exceptions and exception handling.

Also, read the javadocs for ClassLoader.getResourceAsStream to understand how it behaves if it cannot find a resource.

The getResourceAsStream throws a NullPointerException only when the resource name is null.

So if you had tried getResourceAsStream(null), then the catch block would catch the NullPointerException(if mentioned in the clause)

The only exception getResourceAsStream(name) could throw is a NullPointerException and that too, when the name is null. It will not throw any other exception even if the resource is not found.

If you want your code to throw a FileNotFoundException when resource is missing, then use new FileInputStream(String resourceName) (which throws the required file not found exception) to load your resource instead of getResourceAsStream()

Related