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;
}
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()
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)
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:
FileNotFoundException is a subclass of IOException so you are definitely catching it when you catch IOException.
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.
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.
Related
I would like to know how I can avoid try-catch statements. Right now I have a Database handler and every time I run a command I have to surround it in a try block like so:
try {
while(levelData.next()) {
if(levelData.getInt("level") == nextLevel) return levelData.getInt("exp");
}
} catch (SQLException e) {
e.printStackTrace();
}
Can I make it so the actual function throws the exception or something? Rather than having to manually put all these try's in? Its mostly just an aesthetic problem as these try blocks look ugly.
You can throw an exception instead:
public void myMethod() throws SQLException {
while(levelData.next()) {
if(levelData.getInt("level") == nextLevel)
return levelData.getInt("exp");
}
}
Right now I have a Database handler and every time I run a command I
have to surround it in a try block like so...
I think other answers fail to address the above problems. When I started programming with Java, I hated it when my program was filled with try-catch blocks for SQL query statements.
The way I work around it is to use a DAO-level-layer to handle the exceptions. For example, If my program need to access a User table, I create a UserDAO class. Then the queries are created and exceptions are caught in that DAO class.
Every time an exception occurs, I do the logging needed and throw a custom-specified Unchecked Exception, e.g. DatabaseErrorException. The main difference between an unchecked exception and a checked exception (like SQLException) is that you aren't forced to catch or throw it, so it will not fill your code with the throws statement.
(Yes, you can use throws to avoid using try-catch, but you must handle it somewhere anyway, and think about your functions having throws everywhere.)
Then we can have a global filter at the highest level of the application to catch all these exceptions which propagate through the program. Usually a database error can't be recovered from, so here we only need to display the error to the users.
You can make a method throw an exception with the throws keyword, rather than using a try- catch block, but at some point the exception needs to be handled. What I have found most annoying is multiple catch statements, but if you use JDK >= 1.7 they have a multi-catch option available. For exception logging you can use the log4j library.
Let's say I am designing an API for storing passwords. According to Effective Java it is a good idea to use throw clauses to show checked exceptions, however by having a throw clause that throws a SQLException, which is a checked exception, then I am revealing the underlying implementation details of my API and thus I will be unable to change the implementation details of my API at a later stage. One of the pros to throwing a checked exception is that the programmer who uses the API should be able to handle the exception in a manner of their choosing. Which of these two methods should I choose to do, add a throw clause which reveals the implementation or hide it or use a different approach?
Your motivation is correct for not "leaking" SQLException to the users of your class.
The fact that you're using SQL could be considered an implementation detail. You may even swap SQL persistence for say, an in-memory one at a later time, and this change shouldn't impact the users of your class.
If you are inclined to use checked exceptions, I would define your own exception type (say, PasswordStoreException -- just an example name). You can use it to wrap the original exception that was thrown, e.g.:
try {
// do whatever
} catch (SQLException ex) {
throw new PasswordStoreException(ex);
}
It is today considered bad design for an API to declare checked exceptions. If you have ever used such an API, you should already know why.
In any case your API should never throw (let alone declare) exceptions belonging to other APIs. If you do that, you hang a completely unrelated dependency on your client's back. The only "exception" to this rule are JDK's standard exceptions like NPE, ISE and the like.
Catch the SQLException, and wrap it into your own exception:
try {
// JDBC code
}
catch (SQLException e) {
throw new MyException("Error persisting the secret", e); // choose a better name, of course
}
Whether this exception should be a checked exception or a runtime exception depends on what the caller can do about it. If it's recoverable (which, I think, is not the case here), it should be a checked exception. If it's not recoverable (the caller can just display an error message), then it should be a runtime exception.
If it's a checked exception, you have no choice; the exception MUST be declared in the throws clause of the method.
As is, it is always a good idea to throw your own exception checked/unchecked. But before that, try to fix the underlying exception if possible. I always prefer the below way,
try {
// JDBC code
}
catch (SQLException e) {
// try to solve the exception at API level
bollean solvable = trySolveException(e);
if (!solvable) {
// Alert the admin, or log the error statement for further debugging.
mailClient.sendMailToDBAdmin("Some issue storing password", e);
// or
LOG.severe("some issue in storing password " + e.toString);
throw MyException("A request/logstatement is logged on your behalf regarding the exception", e);
}
LOG.info("The exception is solved");
}
finally {
// don't forget to free your resources - to avoid garbage and memory leaks, incase you have solved the issue in trySolveException(e).
}
So,
1) You don't expose the SRQException directly, but you throw your own version of the exception.
2) You tried to solve the exception once and if not you alerted somehow - through a mail or a log statement.
3) Finally, you ve released all the resources if you succeed in solving the exception.
The finally clause can be avoided if you use the new Java7's try with resource close option.
For whether to throw checked or unchecked exception, I will give you an example
1) Say an exceptions like NPE - they are programmatic errors and the developer should be more responsible to have not created a NullPointer. You don't expect your code to account for such careless errors and put a try(NPE), catch(NPE). So throw a unchecked exceptions.
2) On the other hand the exceptions like SQL exceptions are at the rare cases, account for some external dependency. So, better throw a user defined checked exceptions. And the user can determine if he can connect to the backup SQL server if any.
3) There are another clause of exceptions, where the program cannot continue furhter. Say a Memory Out of Bounds. They should be thrown as Errors.
Try this..
fillInStackTrace() method is called to re-initialize the stack trace data in the newly created throwable. Will be helpful in masking the info about the exception when tries to access the API.
For my Java application, I am creating an instance of a user information object and populating it with a service that I don't control the source for.
The code looks like this:
// username given as parameter
UserInfo ui = new UserInfo();
try {
DirectoryUser du = LDAPService.findUser(username);
if (du!=null) {
ui.setUserInfo(du.getUserInfo());
}
} catch (Exception e) {
// Whatever
}
If LDAPService.findUser() can't locate a user, it will throw a NullPointerException and grind the rest of my application to a stop. It's okay if the user information isn't populated, so I want to be able to continue without causing everything else to start throwing exceptions.
Is there a way to do this?
I've upvoted Amir Afghani's answer, which seems to be the only one as of yet that actually answers the question.
But I would have written it like this instead:
UserInfo ui = new UserInfo();
DirectoryUser du = null;
try {
du = LDAPService.findUser(username);
} catch (NullPointerException npe) {
// It's fine if findUser throws a NPE
}
if (du != null) {
ui.setUserInfo(du.getUserInfo());
}
Of course, it depends on whether or not you want to catch NPEs from the ui.setUserInfo() and du.getUserInfo() calls.
You could catch the NullPointerException explicitly and ignore it - though its generally not recommended. You should not, however, ignore all exceptions as you're currently doing.
UserInfo ui = new UserInfo();
try {
DirectoryUser du = LDAPService.findUser(username);
if (du!=null) {
ui.setUserInfo(du.getUserInfo());
}
} catch (NullPointerException npe) {
// Lulz # your NPE
Logger.log("No user info for " +username+ ", will find some way to cope");
}
You are already doing it in your code. Run this example below. The catch will "handle" the exception, and you can move forward, assuming whatever you caught and handled did not break code down the road which you did not anticipate.
try{
throw new Exception();
}catch (Exception ex){
ex.printStackTrace();
}
System.out.println("Made it!");
However, you should always handle an exception properly. You can get yourself into some pretty messy situations and write difficult to maintain code by "ignoring" exceptions. You should only do this if you are actually handling whatever went wrong with the exception to the point that it really does not affect the rest of the program.
It's generally considered a bad idea to ignore exceptions. Usually, if it's appropriate, you want to either notify the user of the issue (if they would care) or at the very least, log the exception, or print the stack trace to the console.
However, if that's truly not necessary (you're the one making the decision) then no, there's no other way to ignore an exception that forces you to catch it. The only revision, in that case, that I would suggest is explicitly listing the the class of the Exceptions you're ignoring, and some comment as to why you're ignoring them, rather than simply ignoring any exception, as you've done in your example.
You are actually ignoring exception in your code. But I suggest you to reconsider.
Here is a quote from Coding Crimes: Ignoring Exceptions
For a start, the exception should be logged at the very least, not
just written out to the console. Also, in most cases, the exception
should be thrown back to the caller for them to deal with. If it
doesn't need to be thrown back to the caller, then the exception
should be handled. And some comments would be nice too.
The usual excuse for this type of code is "I didn't have time", but
there is a ripple effect when code is left in this state. Chances are
that most of this type of code will never get out in the final
production. Code reviews or static analysis tools should catch this
error pattern. But that's no excuse, all this does is add time to the
maintainance and debugging of the software.
Even if you are ignoring it I suggest you to use specific exception names instead of superclass name. ie., Use NullPointerException instead of Exception in your catch clause.
You can write a try - catch block around the line you want to have ignored.
Like in the example code of yours. If you just continue your code below the closing bracket of the catch block everythings fine.
LDAPService should contain method like LDAPService.isExists(String userName) use it to prevent NPE to be thrown. If is not - this could be a workaround, but use Logging to post some warning..
Printing the STACK trace, logging it or send message to the user, are very bad ways to process the exceptions. Does any one can describe solutions to fix the exception in proper steps then can trying the broken instruction again?
I'm writing a program that uses java.net.URLDecoder.decode(String value, String encoding). Apparently, this method might throw an UnsupportedEncodingException, which I get. But I'm just passing "UTF-8" as the encoding. It won't throw that exception.
I could just surround the darn thing with a catch block that does nothing, but then in whatever freak case does cause the exception to be thrown, I won't find out about it. I do not want to create a big chain of throws UnsupportedEncodingException up to the top of my program, either.
What can I do here? Why am I forced to deal with some Exceptions, while others (e.g. IllegalArgumentException, NullPointerException) I'm allowed to ignore?
I think you need a better grasp of checked exceptions and their purpose in general, but that is for another question and answer. In this case what you do is:
try {
//etc.
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e.getMessage(), e);
}
There are two types of exception.
CheckedException: It make you force to use try-catch or throw to the top of program.
UncheckedException: You can bypass.. It would raise on runtime only
I just accept the fact that Java designed that way to make the program less error-prone.
If it bothers you that much, then you can always use the deprecated, single-argument form of URLDecoder.decode(). This doesn't take the encoding parameter, and doesn't throw the checked exception.
Of course, this method is deprecated for a reason - its behaviour depends on the JVM's default encoding, which can vary depending on the operating environment. But if you know that your environment doesn't vary, this may not matter. There's also the risk that the method will be removed in future versions of Java, but no deprecated items have yet to be removed, and I doubt that will ever happen.
Some people wrap RuntimeException to avoid checked exceptions. However in your case you know this exception shouldn't happen. To my mind this is an assertion.
try {
//etc.
} catch (UnsupportedEncodingException e) {
throw new AssertionError(e);
}
Another way to rethrow a checked exception without wrapping it is to throw it as if it were an unchecked exception. You can try this.
try {
// throws a checked exception
} catch (Exception e) {
Thread.currentThread().stop(e);
}
The UnsupportedEncodingException is a checked exception by the URLDecoder.decode method and you must either catch it or specify that your method throws it.
public static String decodeUTF8String(String s) throws UnsupportedEncodingException
{
return java.net.URLDecoder.decode(s, "UTF-8");
}
A good lesson on exceptions
In the following scenario, I was trying to see how to handle this code and it how it relates to Runtimexception. I have read that is generally better to throw runtime exceptions as opposed to rely on static exceptions. And maybe even better to catch a static checked exception and throw an unchecked exception.
Are there any scenarios where it is OK to catch a static exception, possibly the catch-all Exception and just handle the exception. Possibly log an error message and continue on.
In the code below, in the execute1 method and execute2 method, let us say there is volatile code, do you catch the static exception and then rethrow? Or possibly if there are other errors:
if (null == someObj) { throw new RuntimeException(); }
Is this an approach you use?
Pseudo Code:
public class SomeWorkerObject {
private String field1 = "";
private String field2 = "";
public setField1() { }
public setField2() { }
// Do I throw runtime exception here?
public execute1() {
try {
// Do something with field 1
// Do something with field 2
} catch(SomeException) {
throw new RuntimeException();
}
}
// Do I throw runtime exception here?
public execute2() {
try {
// Do something with field 1
// Do something with field 2
} catch(SomeException) {
throw new RuntimeException();
}
}
}
public class TheWeb {
public void processWebRequest() {
SomeWorkerObject obj = new SomeWorkerObject();
obj.setField1("something");
obj.setField2("something");
obj.execute1();
obj.execute2();
// Possibility that runtime exception thrown?
doSomethingWith(obj);
}
}
I have a couple of problems with this code. There are times when I don't want a runtimeexception to be thrown because then execution stops in the calling method. It seems if I trap the errors in the method, maybe I can continue. But I will know if I can continue later on the program.
In the example above, what if obj.execute1() throws a Runtimeexception, then the code exits?
Edited: This guy seems to answer a lot of my questions, but I still want to hear your opinions.
http://misko.hevery.com/2009/09/16/checked-exceptions-i-love-you-but-you-have-to-go/
"Checked exceptions force me to write catch blocks which are meaningless: more code, harder to read, and higher chance that I will mess up the rethrow logic and eat the exception."
When catching an exception and throwing RuntimeException instead, it is important to set the original exception as a cause for the RuntimeException. i.e.
throw new RuntimeException(originalException).
Otherwise you will not know what was the problem in the first place.
Rethrowing checked exceptions as unchecked exceptions should only be done if you are sure that the checked exception is not to be expected.
Here's a typical example:
try {
hash = MessageDigest.getInstance("MD5").digest(string.getBytes("UTF-8"));
} catch (NoSuchAlgorithmException e) {
// Unexpected exception. "MD5" is just hardcoded and supported.
throw new RuntimeException("MD5 should be supported?", e);
} catch (UnsupportedEncodingException e) {
// Unexpected exception. "UTF-8" is just hardcoded and supported.
throw new RuntimeException("UTF-8 should be supported?", e);
}
There are times when I don't want a
runtimeexception to be thrown because
then execution stops in the calling
method. It seems if I trap the errors
in the method, maybe I can continue.
But I will know if I can continue
later on the program.
You have the right idea. The advice about throwing RuntimeException is that it doesn't require the caller to use a try-block or a 'throws' clause.
If your code can recover from an exception than it really should catch it and not throw anything.
One of the first rules about exceptions is to not abuse them to pass state in your application. They should be used for exceptional situations, not as alternative return values.
The second rule is to catch exceptions at the level you process them. Catch and rethrow does not add much. Any cleanup code in your method should be done in a finally block.
In my opinion catching checked exceptions and rethrowing them as runtime exceptions is abusing the system. It feels like working around the "limitations" of design by contract instead of using those "limitations" to get a more robust application.
Whether or not to handle an exception or simply rethrow it depends on your use case.
For example, if you're reading a file to load data into your application, and some IO error occurs, you're unlikely to recover from the error, so rethrowing the error to the top and consequently terminating the application isn't a bad course of action.
Conversely, if you're anticipating recoverable errors then you should absolutely catch and handle the errors. For example, you may have users entering data in a form. If they enter data incorrectly, your input processing code may throw an exception (e.g. NumberFormatException when parsing a malformed number string). Your code should catch these exceptions and return an error the user, prompting for correct input.
On an additional note, it's probably bad form to wrap all your exceptions with RuntimeException. If your code is going to be reused somewhere else, it is very helpful to have checked exceptions to signify that your code can fail in certain ways.
For example, assume your code is to parse configuration data from a file. Obviously, an IO error may occur, so you will have to catch an IOException somewhere in your code. You probably won't be able to do anything about the error, so you will have to rethrow it. However, someone calling into your code may well be able to handle such an error, for example by backing off to configuration defaults if the configuration can't be loaded from the file. By marking your API with checked exceptions, someone using your code can clearly see where an error may occur, and can thus write the error handling code at the appropriate place. If instead you simply throw a RuntimeException, the developer using your code won't be aware of possible errors until they creep up during testing.