2

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;
    }
KnockingHeads
  • 1,569
  • 1
  • 22
  • 42
  • Does this answer your question? [Why is try-with-resources catch block selectively optional?](https://stackoverflow.com/questions/25497053/why-is-try-with-resources-catch-block-selectively-optional) – Gautham M May 05 '21 at 07:12
  • Somewhat, but it specifically refers to exception from close on Autoclosable object and not on specific like FileNotFoundException. Anyways, thanks for that. I will look at that as well. I got to know this only when I could not catch the exception and it made me go bonkers. I had to a lot of manual work which was irritating. – KnockingHeads May 05 '21 at 07:15
  • Are you sure that `FileNotFoundException` was thrown? Because the `catch` clause would catch the exception even if it is not due to `close()`. – Gautham M May 05 '21 at 07:21
  • I was having the application deployed on Wildfly. Initially, I tried changing logging levels thinking that it is not getting logged due to that but no result. So, I tried syso/sout in place as well. But, got nothing. Not sure if it is expected to work like it. Or I missed something, but the code I pasted is the only I had which was erroneous, the rest implementation in try block was nothing. Even it did not print the first print statement I put just inside try saying that it did not go inside try. – KnockingHeads May 05 '21 at 07:26

3 Answers3

1

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.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • And, what if I dont have it in place. Can I log the exception? How can I do that? By having method throw an Exception and handle it at place from where I am calling the method? Because, currently the method in my code doesnt throw an exception which I can handle and I can remove catch as well. – KnockingHeads May 05 '21 at 07:17
  • Answer: because sometimes there is a need, and sometimes there isn't a need. I will take that. Thanks. – KnockingHeads May 05 '21 at 07:19
  • Thanks Stephen, in the comment I have, if I have a sys out only in place of that, the code will still run the same way. Basis: The very sys out I put inside try to debug was not hit. Yes, I can catch exception once I am inside try-with-resources successfully, but what about the one exception that occured when the file could not be found at its path and the stream became null. I dont know if I can consider it an unchecked exception. – KnockingHeads May 05 '21 at 07:40
  • I don't understand your description of your code. But the meaning of unchecked exception is determined by what you "consider" it to be. The distinction between checked vs unchecked exceptions is specified by the JLS. And it is explained here: https://docs.oracle.com/javase/tutorial/essential/exceptions/catchOrDeclare.html – Stephen C May 05 '21 at 07:46
1

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)

1

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()

Gautham M
  • 4,816
  • 3
  • 15
  • 37
  • Yes, I think I can customize the stream part as well and check stream to be null and then throw and log the error as I want. Already made that change in my code. – KnockingHeads May 05 '21 at 07:55
  • @Ashish Instead of checking the `stream == null` and then throwing `FileNotFoundException` and then logging, I would recommend the usage of `FileInputStream` to load your resource, which would automatically throw the exception. Then in the catch clause, you can catch it and log the error as you wish. This would avoid the clutter inside the try block – Gautham M May 05 '21 at 07:59