Java exception handling - Stack Overflow
java - The best way to handle exceptions? - Software Engineering Stack Exchange
Best practice for Java exception handling - Stack Overflow
Exception Handling Guide in Java
Videos
for(File f : files){
try {
process(f); // may throw various exceptions
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
}
You have to use the try/catch/finally blocs.
try{
//Sensitive code
} catch(ExceptionType e){
//Handle exceptions of type ExceptionType or its subclasses
} finally {
//Code ALWAYS executed
}
trywill allow you to execute sensitive code which could throw an exception.catchwill handle a particular exception (or any subtype of this exception).finallywill help to execute statements even if an exception is thrown and not catched.
In your case
for(File f : getFiles()){
//You might want to open a file and read it
InputStream fis;
//You might want to write into a file
OutputStream fos;
try{
handleFile(f);
fis = new FileInputStream(f);
fos = new FileOutputStream(f);
} catch(IOException e){
//Handle exceptions due to bad IO
} finally {
//In fact you should do a try/catch for each close operation.
//It was just too verbose to be put here.
try{
//If you handle streams, don't forget to close them.
fis.close();
fos.close();
}catch(IOException e){
//Handle the fact that close didn't work well.
}
}
}
Resources :
- oracle.com - Lesson: Exceptions
- JLS - exceptions
For the purposes of this method that returns a list, just don't catch exceptions. Let it throw.
Unhandled exceptions in your application still need to be handled, but the error handling occurs much deeper in the call stack. Something closer to main() will essentially wrap the entire application in a try/catch block where it simply prints the message and stacktrace to the error output.
static int main(String[] args) {
try {
// CSV logic/application logic goes here
return 0;
}
catch (Exception ex) {
System.err.println(ex.toString());
return 1;
}
}
This is a fairly consistent pattern across languages and tech stacks. Something closer to the start of the program catches everything and either logs the problem or prints it to the error output of the host OS. This detail is often hidden from us programmers by application frameworks, but it still exists. If your program doesn't catch the exception and handle it then the Java runtime needs to. And if the runtime cannot, then the host OS needs to, which should terminate the application. And if the host OS doesn't, then... I dunno. Reboot.
I'm just guessing, but since this is an example project for learning purposes, I imagine you don't have a full framework, which means you need to write the global error handling logic. When you don't see a better place, put it in main() or whatever function represents the start of a new thread, but keep the error handling logic simple. At that point you just need to report the problem for debugging purposes, especially for toy projects. If there is no way to recover and continue a use case, terminate the program.
In cases where retrying a use case is desirable, then you need to catch exceptions closer to the logic for that use case. For example, in the controller of an MVC application. This allows you to redraw the UI with an error message affording the user an opportunity to correct their input and try again.
Sometimes the best way to handle an exception is not at all.
Since I only want the error and stack trace to be printed in the console and the application to be terminated, what is the best approach to deal with this?
This looks like a job for a throws declaration. In Java, if you're throwing an (ick) checked exception out of the method then you need to say so in the method signature. FileReader throws a FileNotFoundException which is a checked exception.
public static List<Usuario> ler() throws FileNotFoundException {
try (FileReader reader = new FileReader(UsuarioArquivo.getCaminho().toString())) {
return new CsvToBeanBuilder<Usuario>(reader)
.withType(Usuario.class)
.build()
.parse()
;
}
}
Throwing from within a try-with-resources can get interesting but I believe this is all you need here.
This is not for a real application; it's just a simple study project, so if something goes wrong, I just want to know what happened and have the program terminate, nothing more.
Real or not, depending on how you're running the program, just letting the exception go uncaught may already do exactly that. Halting a program that is in an undefined state is a good thing. If you can't recover and put it back into a defined state then it's best to let it halt before it corrupts data, causes a security issue, or sends the president threating emails.
Now maybe you can recover. Either by rejecting the requested task or performing the task in some degraded way. Would your program react well if you simply returned an empty list?
I don't want to handle them in my application, mainly because I don't even know how to handle them.
Well that’s a bad reason to not handle them. Handle them wherever you can see what to do next. Something you were counting on didn’t work out. Can you see what to do next?
Easily 80% of code is just dealing with things going weird. Don’t be surprised if this takes a fair bit of work.
First, unless you have very good reason, never catch RuntimeException, Exception or Throwable. These will catch most anything that is thrown, and Throwable will catch everything, even those things you're not meant to catch, like OutOfMemoryError.
Second, avoid catching runtime exceptions unless it directly impedes with the critical operation of your program. (But seriously, if anyone sees you catch a NullPointerException, they are within their full rights to call you out on it.) The only exceptions you should be bothering with are those that you are required to handle. Out of your list of exceptions, the only one you should bother with is IOException. The rest are the result of not enough tests, or sloppy coding; those shouldn't occur in the normal run time of your application.
Third, in Java 7, you have the ability to do a multi-catch statement for your exceptions, if the exceptions are mutually exclusive. The example linked does a good job of explaining it, but if you were to encounter code that threw both an IOException and an SQLException, you could handle it like this:
try {
// Dodgy database code here
catch (IOException|SQLException ex) {
logger.log(ex);
throw ex;
}
This cleans things up a bit, as you don't have unwieldy and huge chains of exceptions to catch.
First of all the problem with "best practice" advice is that it tends to over-simplify the question and the answer. Then someone (like yourself) comes along and notices that it is contradictory1.
IMO, best practice is to take "best practice" advice and people who regularly use that phrase with a healthy level of suspicion. Try to understand the real issues yourself, and reach your own conclusions ... rather than just relying someone else to tell you what is "best practice".
1 - Or worse ... they don't notice the contradictions, edge-cases, etc, and blindly follow the so-called "best practice". And occasionally, they find themselves in a dark place, because the "best practice" recommendation was inappropriate.
So what's the problem here? It is this statement:
but I also heard that catching generic exception is not a good coding practice.
In fact, it is not normally good coding practice to catch generic exceptions like Exception. But it is the right thing to do in some circumstances. And your example is one where it is appropriate.
Why?
Well lets look a case where catching Exception is a bad idea:
public void doSomething(...) {
try {
doSomethingElse(...);
} catch (Exception ex) {
// log it ... and continue
}
}
Why is that a bad idea? Because that catch is going to catch and handle unexpected exceptions; i.e. exceptions that you (the developer) did not think were possible, or that you did not even consider. That's OK ... but then the code logs the exception, and continues running as if nothing happened.
That's the real problem ... attempting to recover from an unexpected exception.
The (so-called) "best practice" advice to "never catch generic exceptions" deals with the issue, but in a crude way that doesn't deal with the edge cases. One of the edge cases is that catching (and logging) a generic exception is OK if you then immediately shut the application down ... like you are doing.
public void main(...) {
try {
// ...
} catch (Exception ex) {
// log exception
System.err.println("Fatal error; see log file");
System.exit(1);
}
}
Now contrast that with the (supposedly) good practice version in your question. What is the difference?
- Your version produces more user friendly / less alarming diagnostics ... up to a point.
- Your version is significantly more code.
- Your version is unhelpful to someone trying to diagnose the problem because the stacktraces are not recorded.
And the counterpoints to 1 and 2 are:
- You can spend limitless time honing the "user friendly" diagnostics for an application, and still fail to help the kind of user who can't or won't understand ...
- It also depends on who the typical user is.
As you can see, this is far more nuanced than "catching generic exceptions is bad practice".