When to log chained exceptions? - java

I am a green developer trying to get a handle (har-har) on error handling in a large multi-layer java application. There are many situations where I believe that chaining exceptions through several layers is a good idea; e.g. when a failure in calling out to some external service at the lowest layer causes problems all the way up in the view:
Content X requested, but user isn't authorized
caused by: List of authorized users is null
caused by: User-management webservice responded Bad Request- Parameter foo must be formatted like 'xyz'
The most important exception, the one whose stacktrace I really want to examine, is the last in the chain; that I made a bad request and I need to fix foo's formatting. But when I let this exception bubble up through the layers, nicely chained in exceptions that are meaningful to each layer... when I eventually catch and log the thing, the default logging behavior always shows me gobs of detail about the outermost exception, and maybe 5 lines of stacktrace of the root cause.
This makes me want to log exceptions as they happen, AND let them bubble up, but then you end up logging most things twice; when they happen and when they are eventually caught.
What is the best practice here?

I would recommend a different approach of exception management. At the top most layer of the application (like request entry point) create a try catch block to call any runtime exception. It's preferable that you have 2 catch blocks:
- for your application specific (business) exceptions
- for the rest (exception)
As you can see youl'l need to introduce you own exception type that you'll extend to create different exceptions for different purposes. For example you can create a custom exception for every layer of the application, for each integrarion etc. Use unchecked exeptions as they all will be handled on the top level. When any exceptional situation ocures (catch of low level exception) you should:
- Put a description associated with the business context (for example "failed to load account data from DB"
- Add description of the original exception (for example "Original error: Connection to DB failed")
- Pass original exception to your exception in order to not loose the trace
- Throw and forget. In other words top level catch block is responsible to handle it appropriatelly (rollback a transaction, show error message or anything else you may need

Great question, I'm curious about other answers you will get.
I tend to take a "more is better" approach, and log at each step of the way. Does this make large logs? Yes, but when you're debugging an issue in a large Java application, you will be thankful for every log line you have. There are also tools (at the very least the grep, awk, sed trio) to help you filter through large files.
Another technique is to write this logging code, but turn it down (if you're using something like log4j, to the TRACE level). This way, should you run into an issue, you may not have the logs available, but it's a one line change (to lower the logging threshold) and you start generating a wealth of data for debugging.
In tandem with the previous technique, most logging libraries (again I'm falling back on my knowledge of log4j here) allow you to tune the log levels of different java packages. This means that you can write all of these "catch and rethrow" log lines as trace, and turn down the logging on lower level packages to WARN while you keep upper level packages at DEBUG or TRACE.

Related

Where should I add IOExceptions in Java? [duplicate]

I have been coding in Java for a while now. But sometimes, I don't understand when I should throw the exception and when should I catch the exception. I am working on a project in which there are lot of methods. The hierarchy is something like this-
Method A will call Method B and Method B will call some Method C and Method C will call Method D and Method E.
So currently what I am doing is- I am throwing exceptions in all the methods and catching it in Method A and then logging as an error.
But I am not sure whether this will be the right way to do it? Or should I start catching exceptions in all the Methods. So that is why this confusion started in my- When should I catch the Exception vs When should I throw the exceptions. I know it's a silly question but somehow I am struggling to understand this major concept.
Can someone give me a detailed example of When to catch the Exception vs When to throw the Exceptions so that my concepts gets cleared on this? And in my case, should I keep on throwing the exception and then catch it in the main calling Method A?
You should catch the exception when you are in the method that knows what to do.
For example, forget about how it actually works for the moment, let's say you are writing a library for opening and reading files.
So you have a class, say:
public class FileInputStream extends InputStream {
public FileInputStream(String filename) { }
}
Now, lets say the file doesn't exist. What should you do? If you're struggling to think of the answer, that's because there isn't one... the FileInputStream doesn't know what to do about that problem. So it throws it up the chain, i.e.:
public class FileInputStream extends InputStream {
public FileInputStream(String filename) throws FileNotFoundException { }
}
Now, lets say someone's using your library. They might have code that looks like this:
public class Main {
public static void main(String... args) {
String filename = "foo.txt";
try {
FileInputStream fs = new FileInputStream(filename);
// The rest of the code
} catch (FileNotFoundException e) {
System.err.println("Unable to find input file: " + filename);
System.err.println("Terminating...");
System.exit(3);
}
}
}
Here, the programmer knows what to do, so they catch the exception and handle it.
There are two cases when you should catch an exception.
1. At the lowest possible level
This is the level at which you are integrating with third party code, such as an ORM tool or any library performing IO operations (accessing resources over HTTP, reading a file, saving to the database, you name it). That is, the level at which you leave your application’s native code to interact with other components.
At this level, unexpected problems out of your control such as connection failures and locked files may occur.
You may want to handle a database connection failure by catching a TimeoutException so that you can retry after a few seconds. The same goes for an exception when accessing a file, which may be locked by a process at the moment but be available at the next instant.
The guidelines in this scenario are:
Handle only specific exceptions, such as SqlTimeoutException or IOException. Never handle a generic exception (of type Exception)
Handle it only if you have something meaningful to do about it, such as retries, triggering compensatory actions, or adding more data to the exception (e.g. context variables), and then re-throw it
Do not perform logging here
Let all other exceptions bubble up as they will be handled by the second case
2. At the highest possible level
This would be the last place where you can handle the exception before it is thrown directly to the user.
Your goal here is to log the error and forward the details to the programmers so they can identify and correct the error. Add as much information as possible, record it, and then show an apology message to the user, as there’s probably nothing they can do about it, especially if it is a bug in the software.
The guidelines in this second scenario are:
Handle the generic Exception class
Add more information from current execution context
Log the error and notify the programmers
Show an apology to the user
Work it out as soon as you can
The reasoning behind these guidelines
First, is that exceptions represent irreversible errors. They represent represent a bug in the system, a mistake made by the programmers, or a situation beyond the control of the application.
In these cases, there is usually little or nothing the user can do. Thus, the only thing you can do is log the error, take the necessary compensatory actions, and apologize to the user. If it is a mistake that the programmers made, it is best to let them know and fix it, working towards a more stable version.
Second, try catch blocks can mask application execution flow depending on how they are used. A try catch block has a similar function to that of a label and its goto companion, which causes the application execution flow to jump from one point to another.
When to throw exceptions
Easier to explain in the context of developing a library. You should throw when you reached an error and there's nothing more you can do besides letting the consumer of your APIs know about it, and letting them decide.
Imagine you're the developer of some data access library. When you reach a network error, there's nothing you can do besides throwing an exception. That's an irreversible error from a data access library standpoint.
This is different when you're developing a website. You would likely catch such exception in order to retry, but would want to throw an exception in case you received invalid parameters from outer layers since they should have been validated there.
Which is again different in a Presentation layer, where you expect the user to provide invalid parameters. In that case you just show a friendly message instead of throwing an exception.
As featured at https://roaddd.com/the-only-two-cases-when-you-should-handle-exceptions/
An exception should be thrown when a function experiences a failure, i.e., an error.
A function is a unit of work, and failures should be viewed as errors or otherwise based on their impact on functions. Within a function f, a failure is an error if and only if it prevents f from meeting any of its callee’s preconditions, achieving any of f’s own postconditions, or reestablishing any invariant that f shares responsibility for maintaining.
There are three different kinds of errors:
a condition that prevents the function from meeting a precondition (e.g., a parameter restriction) of another function that must be called;
a condition that prevents the function from establishing one of its own postconditions (e.g., producing a valid return value is a postcondition); and
a condition that prevents the function from re-establishing an invariant that it is responsible for maintaining. This is a special kind of postcondition that applies particularly to member functions. An essential postcondition of every non-private member function is that it must re-establish its class’s invariants.
Any other condition is not an error and should not be reported as an error.
Report an error wherever a function detects an error that it cannot deal with itself and that prevents it from continuing in any form of normal or intended operation.
Handle the error in the places that have sufficient knowledge to handle the error, to translate it, or to enforce boundaries defined in the error policy, such as on main or thread mainlines.
Source: C++ Coding Standards: 101 Rules, Guidelines, and Best Practices
In general, catch at the level where you can do something useful about it. For example, user is trying to connect to some database, and it fails in Method D.
How do you want to handle it? Perhaps by putting up a dialog saying "Sorry, cannot connect to SERVER/DB" or whatever. Is is method A, B, or C that created this SERVER/DB information (say, by reading a settings file or asking for user input) and tried the connection? That is probably the method that should handle the Exception. Or at least 1 away from the method that should handle it.
It really varies depending on your application, so this can only be very general advice. Most of my experience is with Swing / desktop apps, and you can usually get a feel based on which classes are doing program logic (e.g. "Controller" stuff) and who is putting up dialog boxes (e.g. "View" stuff). Usually the "controller" should catch the exception and try to do something.
In a web app this can be different.
Some very skeletal code, most of the classes do not exist, and Im not sure if a URL for the DB even makes sense, but you get the idea. Vaguely Swingish...
/* gets called by an actionListener when user clicks a menu etc... */
public URL openTheDB() {
URL urlForTheDB = MyCoolDialogUtils.getMeAURL(URL somePreviousOneToFillInTheStart);
try {
verifyDBExists(urlForTheDB);
// this may call a bunch of deep nested calls that all can throw exceptions
// let them trickle up to here
// if it succeeded, return the URL
return urlForTheDB;
}
catch (NoDBExeption ndbe) {
String message = "Sorry, the DB does not exist at " + URL;
boolean tryAgain = MyCoolDialogUtils.error(message);
if (tryAgain)
return openTheDB();
else
return null; // user said cancel...
}
catch (IOException joe) {
// maybe the network is down, aliens have landed
// create a reasonable message and show a dialog
}
}
I'll share a pattern that has saved my bacon in a production environments or two.
Motivation
My aim is to ensure that the poor dude (maybe me) who is in at midnight trying to resolve a sev1 support ticket, gets a nice hierarchy of 'caused by' errors to follow, complete with data such as ID's, all without over cluttering the code.
Method
To achieve this, I catch all checked exceptions and re-throw them as unchecked exceptions. I then use a global catch at the boundary of each of my architectural layers (usually abstracted or injected so it is only ever written once). It is at these points that I can add extra context to the error stack, or decide whether to log and ignore, or raise a custom checked exception with variables to hold any extra context. On an aside, I only log errors at the top layer to stop 'double logging' from occurring (e.g. the cron job, the spring controller for ajax)
throw new RuntimeException(checked,"Could not retrieve contact " + id);
With this approach there is no cluttering of your GUI or business tier's method signatures by having to declare 'throws' for database related exceptions.
An Example of how this works in Real Life:
Lets say my code's job is an automated process to renew many insurance policies. The architecture supports a GUI to manually trigger renewal for one policy. Lets also say that the postcode for the rating area is corrupted in the DB for one of these policies.
An example of the type of error log I would want to achieve would be.
Log message: Flagging policy 1234 for manual intervention due to error:
From Stack Trace: Error Renewing Policy 1234. Rolling back the transaction ... This catch would also cover errors such as save errors, or generation of a letter.
From Stack Trace: Caused by: Error Rating Policy 1234 ... This catch would pickup errors retrieving many other objects, and algorithm errors such as NPE etc...
From Stack Trace: Caused by: Error Retrieving Rating Area 73932 ...
From Stack Trace: Caused by: JPA: unexpected null in field 'postcode'
You should handle the exception at the lowest possible level. If method can't handle the exception properly you should throw it.
catch If you have method which connects to resource (eg opens file/network)
throw if class higher in hierarchy needs information about error
You generally throws an exception when you want to notify the caller of the method of some failures.
e.g invalid user input, database problems, network outages, absent files
As others have said, as a general rule, you should catch an exception when you can actually handle it, otherwise, just throw it.
For example, if you are writing code that reads information about a connecting player from a save file and one of your I/O methods throws an IOException, then you would want to throw that exception and the code that invoked the load method would want to catch that exception and handle it accordingly (like disconnect the player, or send a response to the client, etc.). The reason why you would not want to handle the exception in the load method is because in the method, you cannot meaningfully handle the exception, so you delegate the exception to the caller in hope that they can handle it.

Best practice on exception and error handling with Selenium and SerenityBDD (thucydides)

Actually I'm writing a bunch of tests but I'm not sure how I should handle exceptions/errors best.
There a different types of exceptions, e.g. AssertException if a result was not as expected using assertThat(..). This is O.K. and understandable.
But what if I have a FileNotFound / SOAPException / DOMException and so on...?
For example in my #BeforeStory method I create some testdata by reading testfiles and sending them to a webservice and there I could possibly get the above mentioned exceptions. I would like to present these errors by using an own error message also in the living documentation. But how should I manage this? Actually I'm thinking about two approaches:
1.) I catch the exception and throw my own new exception with an individual error message. The testexecution is aborted for the scenario and the exception is presented in the living documentation.
2.) I catch the exception, implement a string based return statement with the error message and use an assertThat(...) in my low-level specifications so I only should get AssertException in the end.
3.) ..?
Question: And advice or common best practices how to handle exceptions or errors with selenium/serenity ?
First of all, there is a good source of information for you theme - xUnit test patterns book.
Answering your question, the good approach is using 2 major groups of errors. The first one is AssertionException indicating a problem (bug) in application under test. The second one are all other exceptions indicating problems in test code itself, test execution env or application env, but not in application. Building your tests this way will help you finding and eliminating problems fast.
So generally you are on the right way with your first option. It's a good idea to collect some additional data (e.g. application/execution env) when exception occurs as well.

Always try-catch-finally for exceptions? Central error management?

I wonder if I always have to use try-catch-error blocks that clutter the code a lot, if I want to catch an error.
Or can I somehow define a global error catcher?
Especially regarding Java EE Webapps.
For every unhandled ex I'd like to log to a specific file, and display a general error page to the user.
I thought I might achieve that with aspects. But for aspects to catch on #AfterThrowing, I too have to introduce try-catch blocks. And as there is no central class for the backing-facades, I would have to surround every backing method with trycatches.
Then the aspect would take them, but I need something to catch without explicit throws exceptions.
How could I to that?
You are looking for the declare soft construct. This will wrap the given exception in a SoftException (an AspectJ-specific RuntimeException) so that it does not need to be explicitly handled. Then you can handle all of these exceptions with some AfterThrowing advice.
declare soft only exists in code style AspectJ (ie- there is no annotation for this). So, you will need to compile your code using the AspectJ compiler, but you can still use load-time weaving for this if you like.
See here:
http://www.eclipse.org/aspectj/doc/released/progguide/quick-other.html
And here:
http://www.eclipse.org/aspectj/doc/released/adk15notebook/declare-soft.html
Here's a code snippet that shows how it can be done:
aspect ErrorHandler {
declare soft : Exception : within(*);
after() throwing(Exception e) : handler(e) {
// do something...
}
}
This will route all exceptions in your system through your custom error handler. And you won't need to explicitly catch or throw them.
It's simple and powerful. Perhaps too powerful, though. I'd recommend refining and being more precise about exactly which exceptions should be softened and which ones need to be advised, but this is the basic idea.
You don't have to do this in every method.
You should not catch an exception that you can't "handle". Handling means more than just rethrowing or logging or printing a stack trace. I think handling means implementing a meaningful recovery strategy.
It might mean "the buck stops here": You're Gandalf on the bridge at the edge of a layer boundary, and no exception shall pass. You don't want users to see nasty messages, so you catch and route them to a friend, easy to understand page that tells them what to do next.
Finally isn't always necessary, but it's perfect for cleaning up resources like file handles and database cursors.
If you cannot handle an exception, there's no shame in adding the throws clause to the method signature and letting callers figure out what they want to do.
In the general case, there is no mechanism to do this - Java does not have what you're looking for.
However, depending on your circumstances, it might be possible.
web.xml Exception Handler
The web.xml file allows you to define a URL to be used to handle specified exception type. (See, for example, http://wiki.metawerx.net/wiki/Web.xml.ExceptionType).
Since you're writing a webapp, you may be able to just let the exceptions throw all the way to the top, and then handle them this way.
Custom interceptor
You mention that you have backing-facades. Depending on how they're being constructed, you may be able to put a generic proxy in front of them to catch and handle the exceptions you're interested in. You've tagged your question with spring, to you might want to look at Spring AOP Proxies.
There might be other ways to get what you want, but it will depend on the specifics of your application's architecture.
The finer control you have of the exceptions, the easier it will be to debug/provide a meaningful message.
To which extent? I would link that to the complexity / expected lifetime of your application. The bigger those are, the finer should be your handling.
I see two main approachs:
User approach: You get at least one exception handling for each UI action (so you can say: "Do not push that button AGAIN").
Debugger approach: Every method has its control.
Keep in mind that most handling could be just logging of rethrowing of the exception.
More to the point, most probably, your Java EE framework will have log options in its configuration files (many of them working with java.util.loggin or log4j). You could tweak that; of course, what is send to each log category will depend of the framework implementation (so maybe not all ERROR messages will be Exceptions).

Exception Handling in a Java Web Application

I am developing a medium size Java Web Application with Struts as MVC framework and simple JDBC at Data Access Layer. I have been searching for exception handling best practices in such an application. I have found several articles, some of them being contradictory, only making me more confused rather than making things clear and simple. Some say it is better to reuse existing exceptions instead of defining application specific exceptions, others present a huge hierarchy of application specific exceptions for every minor trouble that may occur in the system. Some say it is better not to handle exceptions at Data Access Layer and delegate them to the Service Layer, others say Data Access Layer exceptions should be caught locally since delegating them to Service Layer would violate the abstraction between the two layers. And so on.
I would highly appreciate if you let me know of links/names to articles/books that present solid solutions which have worked for you in such a scenario. The solution should clear at least the following points with justifications:
Where the SQLExceptions be caught?
Where exceptions should be logged?
Should unchecked exceptions be logged?
Should unchecked exceptions be caught at presentation layer, and should they be shown to the user?
How checked exceptions be handled, which of them to be shown to the user and how?
How should a global exception handler page be used?
How should struts ActionErrors be used in this context?
Thanks
1: Where the SQLExceptions be caught?
In DAO classes in data access layer. You can if necessary wrap it with a custom DAO exception. This DAO exception in turn needs to be handled further as checked exception.
2: Where exceptions should be logged?
At the moment when you're about to throw them or to pass through the messaging framework.
3: Should unchecked exceptions be logged?
They should certainly be logged. They should namely not occur in real world, because those are sign of a fault in the code logic (i.e. developer fault) which needs to be bugfixed asap. They should be thrown all the way up to the container and let the container handle them with an <error-page> in web.xml. To log (and eventually mail) them, use a Filter which listens on the error page.
4: Should unchecked exceptions be caught at presentation layer, and should they be shown to the user?
They should not occur at all.
5: How checked exceptions be handled, which of them to be shown to the user and how?
If they are result of errorneous user input (e.g. not a number, bad email, constraint violation, etc), show them in the same form to the user. Otherwise (e.g. DB down, DAO exception and so on) either throw it all the way up to the error page, or display the error with a message to try again later.
6: How should a global exception handler page be used?
At least in an user-friendly manner. Thus, in the same layout, with some introductory "sorry" and if necessary with some error details and an email address so that the user can contact for the case that.
7: How should struts ActionErrors be used in this context?
Show them in same form to the user.
If you can't recover from an exception, then you should let it flow out of your code (often by making it unchecked, or wrapping it in an unchecked exception). If they remain checked, you have to cater for them at each level of your code, and consequently at every abstraction layer. SQLExceptions would normally fall into this category (you'll have to wrap them since they're checked).
For these exceptions, I normally log at the highest level, but present a page to the users simply detailing that something has gone wrong. Normally my users aren't interested in stack traces. But I usually offer them a page to let them describe what they were doing at the time, and the logged exception ties back to this submission via a unique id (recorded in the form and in the log file with the exception). That allows me to tie back users' actions to the resulting exception.
The above assumes that you can't recover from SQLExceptions, and if the database is down, then you can't do something meaningful. There are exceptions to this, of course. You may find that you're talking to multiple systems, and one being down doesn't mean you can't continue in some fashion (e.g. the Amazon home page reportedly relies on 100 services, and needs to run regardless of some of these being down).
I would expect declared exceptions to be at the same level of abstraction as the interface/methods defining them. e.g. a TradeStore would be declared to throw a TradeException, not a SQLException (since methods of storing a trade are an implementation of TradeStore - you could store in a relational db, a JavaSpace etc.).
As a warning, when displaying lower level error messages to users, make sure they're sanitized of system information. This is an area where many security exploits originate. Log them with full information, but only display a more general error message to the user.

Java - where and how should exceptions be used?

I was reading some things about exception handling in Java, to be able to write better code. OK, I admit, I am guilty; I've used too much try-catch{} blocks, I've used ex.printStackTrace() in the catch, not even using a proper logger (actually the System.out and System.err were redirected to a PrintWriter, so a log was generated). However, after a few hours of readings, I find myself in a strange place: the unknown. If the exceptions are designed to pass info about abnormal states of flow, how does one know WHERE is the proper level to do something with that info?
For instance, when a database error occurs, should one return a null value or an error code, or throw the exception? If thrown, WHERE should that exception be handled? I understand that is no use even to log an exception if you cant do anything about it. However, in GUI apps, that could easily kill your GUI (I am using SWT and I've seen this too often), even for the case of the menuShown() method (an ArrayIndexOutOfBounds exception will close the app, if not handled). The example could go on forever, but here's the summary of questions:
Does using try-catch() excessively have a negative impact on performance?
Is it better to use specific exception types? What if I missed catching one
of the possible X types of exceptions that could occur?
Frankly, I've heard of and use a mere 10% I think of the Java standard exceptions, in 2-3 years. Yes, someone said that if the caller don't know how to deal with the thrown exceptions, he SHOULD NOT HAVE THE RIGHT to call the throwing method. Is that right?
I've read this article of Anders
Hejlsberg, saying that checked exceptions are bad. Should that indicate that convenient exception swallowing is advised in some cases?
A picture is worth 1000 words; I guess some examples will help a lot
here.
I know the subject is eternal, but actually I am looking forward to review a middle-size project of 150 classes, using your advice. Many thanks.
The general rule of thumb for exception is, if you can do something about it, catch it and handle it, if you can't, re-throw it to the next method. To get into some of your specifics:
No, using excessive try/catch will not have a performance impact
Using the most specific type of exception you can. For example, you shouldn't generally throw Exception if you can avoid it. By throwing a specific type, you are letting the user know what can go wrong. However, you can rethrow it as something more generic so callers that are not concerned with the specific exception don't need to know about it (for example, a GUI won't care if it's an IOException vs an ArrayIndexOutOFBoundsException).
You will find people that like checked exceptions more and you will find people that like unchecked more. In general, I try to use unchecked exceptions because there is generally not a lot you can do about most checked exceptions, and you can still handle unchecked exceptions, you just don't have to. I frequently find myself rethrowing checked exceptions since I can't do much about them (another strategy is to catch a checked exception and rethrow it as an unchecked so classes higher in the chain don't need to catch it if they don't want).
I generally like to log exceptions at the point of where they are caught - even if I can't do anything about it, it helps to diagnose the problem. If you are not familiar with it, also look into the method Thread.setDefaultUncaughtExceptionHandler. This allows you to handle exceptions that are not caught by anyone and do something with it. This is particularly useful with a GUI app since the exception might otherwise not be seen.
To get into some examples:
try {
// some database operation
}
catch (IOException ex) {
// retry the database operation. then if an IO exception occurs rethrow it. this shows an example doing something other than just catch, logging and/or rethrowing.
}
I'll be happy to expand on any parts of this if you'd like.
Many good answers, let me just add a couple of points that haven't been mentioned.
Your exception types should be as specific as a caller is likely to distinguish them. By that I mean, if there are two possible errors, A and B, and any caller is likely to do exactly the same thing in both cases, then make a single exception class. If a caller is likely to do two different things, then make two exception classes.
For many, probably most, of the exceptions that I create, the only thing the program can realistically do is display an error message and give the user the opportunity to change his inputs and try again. Most validation errors -- invalid date format, non-digits in a numeric field, etc --fall into this category. For these I create a single exception type, which I usually call "BadInputException" or "ValidationException", and I use that same exception class throughout the system. When there's an error, I 'throw new BadInputException("Amount must contain only digits")' or some such, and then have the caller display it and let the user retry.
On the other hand, if the caller is reasonably likely to do different things in different cases, make them different exceptions.
Easy rule of thumb: If you have two or more exceptions that are ALWAYS handled with identical, duplicate code, combine them into a single exception. If your catch block is doing additional checking to figure out what kind of error this really is, it should have been two (or more) exception classes. I've seen code that does exception.getMessage and then looks for keywords in the message to figure out what the problem was. This is ugly. Make multiple exceptions and do it cleanly.
There are three good reasons to use exceptions rather than other ways of handling errors.
(a) It avoids the problem of "magic" return values, like non-null string is a real answer but null means there was an error. Or worse, "NF" means file not found, "NV" means invalid format, and anything else is the real answer. With exceptions, an exception is an exception and a return value is a return value.
(b) Exceptions neatly skip the main line of code. Usually when there's an error you want to skip a whole bunch of processing that does not make sense without valid data, and go right to displaying an error message and quitting, or retrying the operation, or whatever is appropriate. In the bad old dies we would write "GOTO panic-abort". GOTOs are dangerous for all the reasons that have been much discussed. Exceptions eliminate what was perhaps the last remaining good reason to use a GOTO.
(c) Perhaps a corrollary to (b), you can handle the problem at the appropriate level. Sometimes when an error happens you want to retry the exact same function -- like an I/O error might represent a transient communications glitch. At the other extreme, you could be ten levels deep in subroutines when you get an error that cannot be handled in any way but bombing out of the entire program and displaying a "sorry, armageddon has occurred, everybody in here is dead" message. With exceptions it's not only easy to choose the correct level, but you can make different choices in different modules.
Exception is there so the programmer of a Task does not have to deal with the problem by himself. (1): In case the problem is NOT LOGICAL to him to handle in the Task.
A task to read a String from a stream should not handle disk error isn't it. But it should be very logical to handle if data does not contain a String.
(2): He can't handle it by himself (not enough info)
A task to read a String from a file and file not found may ask user to select another file but how can the task now what folder the file might be what extension the file might be. Without knowing that, how can the task create a GUI to re-ask that.
(3): There is no logical (or manageable) way to distinguish between different return.
If a task can't read the file and return null. What about if the file in the wrong format, return null too? How can these two differ? Exceptions can be used to differ that. That why it is called an Exception :-D.
(4): There are many similar tasks that need similar handling and writing that in all tasks is hard to maintain.
Writing the handle code for all access can be a mess as you may require many duplications.
interface DBAccess {
public Result accessDB();
}
class DBOperation {
static public void DoOperation(DBAccess pAccess) {
try { return DBAccess.accessDB(); }
catch(InvalidDBPasswordException IPE) {
// Do anything about invalid password
}
catch(DBConnectionLostException DBCLE) {
// Do anything about database connection lost
}
// Catch all possible DB problem
}
}
...
private User[] ShowUserList_and_ReturnUsers() {
// Find the used.
// Show user list
if (Users.count() == 0)
return null;
else return Users;
// No need to handle DB connection problem here
}
private User[] GetUserProfile() {
// Find the used and return
// No need to handle DB connection problem here
}
...
/** An onClick event to show user list */ {
DBOperation.DoOperation(new DBAccess() {
public Result accessDB() {
return ShowUserList_and_ReturnUsers();
}
});
}
/** An onClick event to show a user profile */ {
DBOperation.DoOperation(new DBAccess() {
public Result accessDB() {
return GetUserProfile();
}
});
}
... Many more DB access
(5): Writing all the checking for error complicate or slow down the task.
The above problem should show how can it help reduce the complication. Here is how it help not to slow down.
for(int i = 0; i < Users.length; i++) {
User aUser = Users[i];
// Do something with user
}
Replaced with
try {
for(int i = 0; ; i++) {
User aUser = Users[i];
// Do something with user
}
}
catch(ArrayOutOfBoundException AOBE) {}
The replacement code will be better performance if the number of user is large.
When a database error occurs, should one return a null value, and error code or throw the exception?
Ans: Depending on what kind of error. Like if you can't find a user, that is not an error. But if the password is wrong or the connection is down, these are errors as trying to handle it in a normal way complicate the program.
(1). Using excessive try-catch() has a negative impact on performance?
Ans: According to "Effective Java", it has very very tiny effect (only not good in loop) as far as I remember (I don't have the book with me here now).
(2).
Using specific exception types is better?
Ans: User specific one is better to avoid solving the wrong problem.
What if i missed to catch one of the possible X types of exceptions that could occur? Frankly, I've heard and use a mere 10% i think of the Java standard exceptions, in 2-3 years.
Ans: Just like if you handle the error without exception, You can miss it too. You simply add it in when you find that out.
Yes, someone said that if the caller don't know how to deal with the trowed exceptions, he SHOULD NOT HAVE THE RIGHT to call the throwing method. Is that right?
Ans: No, if I don't know what to do with some exception, re-throw it.
(3). I've read this article of Anders Hejlsberg, saying that checked exceptions are bad. Should that indicate that convenient exception swallowing is advised in some cases?
Ans: I think he is talking about "Checking exception" as a feature for the compiler to ensure that some exception should be handle. The the idea of having exception.
(4). A picture is worth 1000 words..i guess some examples will help a lot here.
Ans: The code above.
I got the run now .... Sorry ... :-p (Be there in a minute, honey!!)
One thing that we have done on our team is to have custom exceptions for our errors. We are using the Hibernate Validator framework, but you can do this with any framework, or stock exceptions.
For example, we have a ValidationException to handle validation errors. We have a ApplicationException to handle system errors.
You DO want to minimize your try-catch-ing. In our case, we will have the validator collect ALL the validations in "InvalidValue" objects, and then throw a single ValidationException with the invalid value information bundled into it. Then you can report to the user which fields were in error, etc.
In the case you mentioned of a database error - you may not want to send the stacktrace to the UI (logging it is a good idea). This is a case where you can catch the database exception, then throw your own ApplicationException to your GUI. Your GUI won't have to know how to deal with an infinite number of server errors, but can be set to deal with the more generalized ApplicationException - possibly reporting that there is a problem with the server, and indicating that the user should contact your customer support department to report the problem.
Lastly, sometimes you can't help but use a lot of try/catch blocks because of the external APIs you rely on. This is fine. As mentioned before, catch the external exception, and format it into one which makes more sense to YOUR application. Then throw the custom exception.
While I don't have any numbers, I don't believe that try-catch has any significant impact on performance (not that I have seen). I think that if you don't run into many exceptions, the performance impact will be basically nothing. But in any case, it's best to care about implementing code correctly first and achieving good performance second -- a lot easier to do the second once the first is done.
I think the exception class should be specific as to what the exception really is. The problem I have with Java's SQLExceptions is that they give you no information about what really went wrong. Spring uses far a set of more descriptive database exceptions (deadlock exceptions, data integrity exceptions, etc.) That way you can tell what the problem really was.
Checked exceptions can be annoying, but I don't think they're always bad. For example, Spring uses unchecked exceptions for database errors, but I still check for them and either 1) handle them right there, if possible, or 2) wrap in a more general exception that the shows that the component failed.
Unfortunately, I can't think of any good specific exceptions. However, like I said, I've found Spring's exception rules to be helpful and yet not annoying, so maybe you could look at some Spring docs. The Spring database classes are a good example.
Using excessive try-catch() has a negative impact on performance?
This sounds like micro optimization and, if this really has a performance impact, you'll have to deal with a lot of bigger performance problems before to face this one.
Using specific exception types is better? What if i missed to catch one of the possible X types of exceptions that could occur? Frankly, I've heard and use a mere 10% i think of the Java standard exceptions, in 2-3 years. Yes, someone said that if the caller don't know how to deal with the trowed exceptions, he SHOULD NOT HAVE THE RIGHT to call the throwing method. Is that right?
I'm not sure I understood the question but I'd say: "If you don't know what to do with an exception, re-throw it".
I've read this article of Anders Hejlsberg, saying that checked exceptions are bad. Should that indicate that convenient exception swallowing is advised in some cases?
Hell no. This just means that unchecked exception should be preferred in some cases especially when the user won't know what to do with a checked exception (e.g. SQL exception), or if there is not possible recovery,...
A picture is worth 1000 words..i guess some examples will help a lot here.
Spring's DataAccessException is a very good example. Check chapter 10. DAO support.
se-radio made a podcast episode about that topic of error handling that explains some philosophy about how to use exceptions, which can be restated as "Where to absorb them".
The main thing I retained is that most functions should let them bubble up, and most exceptions details should end up in a log file. Then the functions pass only global messages saying that something happened.
In a sense, this leads to a sort of exception hierarchy : one for each layer of code.
As I think they said, it doesn't make sense to explain to the user that such DB cluster failed because the DNS was unavailable, or because the disk was full. At that level, something happend that couldn't allow the transaction to complete, that's all the user has to know.
Of course, the developpers/administrators will be happy to see more details, that's why at the DB layer, the specific exceptions should be logged.
Return value vs. throwing an exception
The fundamental difference between an exception and a return value is that the return value is delivered to your immediate caller, whereas an exception is delivered to a catch clause anywhere in the call stack. This allows to reuse the same exception handler for many different kinds of exceptions. I recommend that you favor exceptions over return codes if and only if you need that feature.
Performance impact.
Every instruction has a negative effect on performance, including those in catch-blocks. However, any modern CPU can throw and handle millions of exceptions per second, so unless you throw thousands of them you won't notice a thing.
Specific exceptions
For throwing, be specific to allow specific handling.
For handling, you can be generic, but you should be aware that arbitrary exceptions can be delivered to your handler, including unchecked ones not declared by your callees.
checked
The debate rages whether methods should use checked or unchecked exceptions.
Never just swallow an exception. Handle or rethrow it. It simplifies maintenance if you don't discard evidence about failures.
Example
An application I worked on recently receives commands over the network which it then executes. This usually involves further interaction with remote systems, which might fail for a host of reasons. The methods to carry out the command don't catch any exceptions, letting them bubble of the call stack to the central exception handler in the command listener, which does the following:
for (int retries = 0;; retries++) {
try {
commandService.execute(command);
return;
} catch (Exception e}
Log.error(e);
if (retries < 3) {
continue;
} else {
saveForAnalysis(command, e);
alertOperator();
return;
}
}
}
We intentionally did not catch & rethrow exceptions in the processing logic, as we felt this would have added no value.
Please, do not return null in case of non-fatal errors. Return a NullObject instead.
Otherwise you need a null check after each and every call to your code which is a pain, and if forgotten will cause the code to crash.

Categories

Resources