Java Propagating Exceptions - java

When would you want to propagate an exception to another Class/Method versus catching the Exception in the same Class/Method?

You catch the exception where you have to handle it.
As a rule of thumb, you should let your exceptions bubble up, but if you don't want your subroutine to crash due to a (possibly expected) error, than you handle the exception, which normally involves logging an error and/or displaying an error message to the user.

The good practice is "throw early and catch late". That allows you to better understand the cause of the exception.

This topic is fairly broad; fortunately there are good resources already in place:
Guidelines on Exception propagation (in Java)
http://www.javacodegeeks.com/2012/04/exception-handling-guidelines-best.html
Best practices for exception management in Java or C#

The great majority of exceptions occuring in real-life code are not recoverable in the sense there's any meaningful code that will retry the operation or try to do it differently. The only recovery happening is aborting the current unit of work in an orderly manner—logging the exception, releasing any resources and similar.
This means that, as a first rule, you'll always want to propagate the exception towards that well-defined exception barrier that demarcates your unit of work.
If your code demands anything different than this, it is probably going to be obvious enough, so you don't need to think about it in the general.

Related

When is throwing/catching general exception acceptable

One of the projects I inherited is riddled with tons of try/catch blocks catching the general Exception. I've been slowly but surely refactoring this, but there are so many, such that I have been contemplating bringing this up as a concern in a meeting. This got me to thinking...Is there ever really a case where catching the general exception is justified in a production environment? I could not think of a case where I NEEDED to catch the general exception, but I'm also a fairly recent grad and I'm sure there's tons that I don't know. I did a little research, and I can find lot's of reasons why NOT to catch the general exception, but nothing concrete on when this practice is justified. Obviously if you're calling a method that already throws Exception you have to catch it. But is there ever a reason some method could throw Exception and it should not be refactored to throw the specific exception.?
Throw Exception only if you need to throw Exception, specifically. If you throw too-general an exception, you are effectively just shouting "there is a problem", without giving specific information as to what that problem is.
Catch Exception only if Exception is thrown, specifically. If you catch too general an exception, you're losing the opportunity to handle specific exceptions in the correct way.
Throwing Exception is the equivalent of returning Object instead of a more-specific type which would be useful to the caller; catching Exception is the equivalent of assigning a return value to an Object variable, rather than a more specific type that you could do useful things with. Basically: you are discarding available type information.
Sometimes you have to throw Exception, because you are writing a general framework. For example, Callable.call throws Exception, because you don't know what code will be executed there, so allowing it to throw Exception means that you don't constrain users of the class. And consequently, if you're calling a Callable, you need to catch Exception; but you need to do it with care.
The vast majority of people aren't (or shouldn't be) writing frameworks, and so you shouldn't be throwing or catching Exception.
There is good advice on this in Effective Java, Item 61, " Throw exceptions appropriate to the abstraction" (this is the number in 2nd Ed; don't know about 3rd Ed). Basically: you almost certainly don't want to throw Exception, but you might want to throw IOException rather than FileNotFoundException, if the fact that you're reading from a file isn't relevant to your API.
Catching general Exception isn't best practice, because if you are catching exception you are telling that you can handle it and recover from that exception state, but if you can't recover then it might be better to fail than to keep working with very unpredictable state.
Another thing that can happen is to catch exception that is supposed to be handled at higher level which can again lead to dangerous state.
There is possibility that code was written before Java 7 when multi-catch was introduced so they used Exception instead of writing each separately, or that developer wasn't familiar with this.
Only case in which catching Exception is justified, in my opinion at least, is at top of the application(main) - catch all exceptions that are not handled at lower levels, log them and exit for safety reasons, and crash nicely and show reasonable message to end user.
This brings us to another thing, and that is throwing Exception, same as with catching one you shouldn't throw Exception, that is same like returning Object from every method, you lose identity.
If this two things are very common in project you are working on maybe you should consider mentioning that to senior developer.

Java Error handling - is it better to throw Exceptions to centralized error handlers?

I've got a decently complex little game going on in Java (solitaire, essentially like the Windows version), but I have yet to do very much error handling.
Almost all of the methods across my classes will end up either getting called by an initial constructor (eventually main()), a paintComponent() method, or a mouse event. So, my question is, is it bad practice to just use "throws Exception" on all of my lower-level methods, and only do a try/catch at my top-level methods to catch ALL the errors at once? (e.g. 3 try/catches - one for the painting, one for mouse events, one for the main method).
I realize this prevents me from easily dealing with errors on-the-spot, but I don't really plan on doing that anyways. My error handling is going to consist of writing to a log, telling the user, and killing the program. Keeping this in mind, is there anything bad with doing my error handling this way?
It depends on how you want to approach the situation.
If you just want to catch any possible exception and you don't mind about the handler code, you could simply use "throws exception", and there's nothing BAD with it either. It's like a try-catch block that covers all the function.
If you want to write specific code for specific exceptions, you should use try-catch blocks to write appropriate code for each handler.
Based on what you're saying, any caught exception would just notify the user and exit the application. Well, in this case you could just use the first approach. It's not necessarily the BEST approach, and neither is killing the application, however, if that's your strategy you could just use "throws" for each function.
Hope that helps!
If that's all you wan't to do in a case of an error, then it makes perfect sense to do it that way. This eliminates code duplication and scattering of related code. However, if you're thinking of changing how things work in the future (if there's a possibility of this happening), I would suggest to try and push the catch down as far as possible (maybe even eliminating the need for exceptions at all and just logging and exiting right away).
If you use the exception's inner fields (specifically message, which you can set in construction time), you can even eliminate the need for 3 different catch blocks and just use one (depending on your actual actions in case of an error, of course).
I wouldn't - the big reason being that it breaks encapsulation. The reason why this is important in this case is that your error handling code has one of two futures:
Becoming enormous to handle in an informative way every error the program can throw.
Be tiny but not helpful at all: "Some error occurred somewhere".
To my mind, the best structure is to catch the error, log it, alert the user, and exit as far down as possible. There's nothing that says your mouse handling code can't exit, right?
In fact, I would create an error handler class that you can call from just about anywhere, and it handles the notification and logging. Then your exception handlers can just populate it with the message to display/log, and all other code is shared. It will cost you less typing to delegate to this class than adding throws Exception at the end of every function everywhere.
If you must have a top level handler, it should just catch any unexpected runtime errors, so that you can log it and show the user that the program is really quitting for an error, and not just dump to the desktop. All other errors - even if you just want to bail out - should be caught as close to "where the exception has meaning" as possible.
I do the same thing as you are describing most of the time. What you're basically doing is working around the stupid checked exceptions that Java has. It shouldn't even be necessary to add 'throws Exception' everywhere.
If I'm working on an API that other users will use I may create specific exceptions to show what is going on in case they want to handle different exceptions in different ways.
If an error is severe enough to always exit the program, you may be better of throwing a RuntimeException instead. They are used to indicate unrecoverable errors and will avoid problems with putting "throws Exception" everywhere. You should have a handler for RuntimeExceptions anyway to provide a user-friendly error report in case they happen.
If you throw checked exceptions, they should be as specific as possible. Throwing and catching Exception can hide other exceptions that are thrown (including RuntimeExceptions) that you didn't intend and could have been handled differently. If you want to throw a general exception, you can always create your own exception class and throw that instead.
The exception handling can depend on the context so there's not one way to handle everything. If the user clicks a button to open a file and there's an error reading it, then it would be ok to throw an IOException up to the UI layer and display an error message there. On the other hand, an IOException while creating a temporary file could be handled lower down by retrying in another directory.

Better understanding exceptions and logging in a J2EE environment

I'm trying to better understand exception handling and logging in a j2ee environment to refactor some legacy code (we use log4j for our logging mechanism). Most of our current code does something like the code below on the business tier, however, I'd like to switch over to unchecked exceptions and just ignore them unless it makes sense to handle them somewhere:
try {
doSomething();
} catch (MyException e) {
log.error("Exception:", e);
throw e;
}
After the exception is thrown in the business tier, it is then propagated up to the presentation tier, which again catches the exception and usually wraps it in a PortletException or ServletException and throws it again. Then, it is handled by a Spring handler which shows a 'friendly' message to the user. I'd ultimately like to only handle exceptions for which we want to show a specific error message, and just ignore everything else.
Questions:
Is it necessary to log exceptions in the business tier? If not, do
I need to log exceptions at all (especially unchecked ones)?
What happens to uncaught exceptions that are not logged using log4j?
(If they're still printed in the console, what's the purpose of
log4j?)
I am confused as to how the process works...
Thanks.
EDIT: If an exception occurs in an outside library (Spring, Hibernate, etc), is it assumed that these exceptions will be printed out using whatever logging mechanism is being used? In that case, I guess that I would only need to log the exceptions that my code throws... or am I way off base here?
Before proceeding any further, please take a careful look at:
The following are some of the generally accepted principles of
exception handling:
If you can't handle an exception, don't catch it.
If you catch an exception, don't swallow it.
Catch an exception as close as possible to its source.
Log an exception where you catch it, unless you plan to rethrow it.
Structure your methods according to how fine-grained your exception handling must be.
Use as many typed exceptions as you need, particularly for application exceptions.
Point 1 is obviously in conflict with Point 3. The practical solution is a trade-off >?between how close to the source you catch an exception and how far you let it fall before you've completely lost the intent or content of the original exception.
IBM DeveloperWorks: EJB best practices
It is usually advised that you use checked exceptions for application exceptions at the business tier. I prefer to follow the business interface pattern to decouple the business tier from the user interface and web tier. This will allow me to think of your business tier as a service layer library and callers might want to handle different situations differently when calling this layer. That is one reason you might want to include checked exceptions, since you can react differently to different exceptions. Furthermore, including checked exceptions will usually help the caller code to be better aware of what different situations might arise from invoking some functionality. It could be worth it to take a look at the business delegate pattern and how it might help you with exception handling. In short, the business delegate pattern allows you to create a very thin layer between the business layer and the web layer where you can do things like exception handling.
No matter how you go about doing this, make sure that you understand the implication of adding an application exception to your Java EE application. You may need to investigate how it interacts with your transaction management logic, specifically when it comes to transaction rollbacks. In my line of work, I had to add an #ApplicationException(rollback=false) to forbid the transaction manager from rolling back my transaction when an exception is thrown and propagated upwards.
You may be able to tell I was working with EJB, but the concepts are probably very applicable to your design as well.
So back to your questions:
Is it necessary to log exceptions in the business tier?
It is not necessary if you plan to log it later on. You better devise a logging strategy at a high level and log all caught exceptions there.
If not, do I need to log exceptions at all (especially unchecked
ones)?
I think that you should log exceptions because that will help you debug any issues later on. The user is usually not savvy enough to capture any output that might be produced if the exception propagates and gets printed on his/her screen without you handling it.
What happens to uncaught exceptions that are not logged using log4j?
(If they're still printed in the console, what's the purpose of
log4j?)
I think it will eventually be caught by the web container and be printed out to the console. If an exception propagates upwards and reaches the web container exception handling safety nets, your exception is out of control. It is usually a sign of bad design. It is best if you keep your exceptions under control. Why wonder how a container will react to an uncaught exception? Also how beneficial will that exception be to the user? I think the information presented from uncaught exceptions are almost useless, as they are so far from the source of the error, that they become irrelevant and hard to work with when debugging.
You could create your own exception hierarchy to wrap them to quickly identify from where in your application architecture it is originating. Also one can go a step further to provide codes and reasons that covers majoority of the use cases.
What logging helps you is to identify the sequence of events, when potentially multiple clients are slamming the same use case or hitting a bottle neck. The logging give you a sequence to trace back because requests increasesed there was congestion in this query causing it to timeout and thus other users where seeing another exception.
While handling the application and showing it to the user is another issue.
Cheers!
We definitely do not have to handle exceptions just to log them. I believe we should catch exception if we then throw other exception that contains the source exception as its cause or if we implement some logic that must be implemented in current layer when exception is thrown.
Yes, it is a little bit verbose to declare all methods as throws MyException. This is the reason that Spring (that you use) prefer working with unchecked exceptions. BTW this is the new feature in Java 7: you can ignore exceptions without declaring that method throws it.
I believe that we still need checked exceptions for development of libraries that expose API to 3rd party applications. Application layer exceptions should be mostly runtime and be caught in one central place.
Is it necessary to log exceptions in the business tier?
No. But more logs = better understanding what is going on. In other way more logs = lower performance.
What happens to uncaught exceptions that are not logged using log4j?
You lost them. Logger pretty things that you can save logs in the place where you need and use filters to get only actual logs for now.
You don't need to catch the business exception (as long as it's unchecked). You don't need to handle them or to log them. You can just swallow them. The problem is - what is such exception for?
Exception signals some inappropriate behaviour in the workflow of your application. If it's checked you, typically, can do something about it - try do some operation again, do some workaround, try different action, etc.
If it's unchecked, it is typically an exception you don't know how or can't handle.
It's considered a code smell if all you do is catch an exception and log it. It's not as bad as swallowing it, but still - it's not good.
Some of the containers (i.e. EJB) is required to log occurred exceptions. Moreover, in EJB 3.x if you're in a JTA managed transaction, and you won't catch an unchecked exception which is not marked as #ApplicationException(rollback=false) than the transaction will be automatically rolled back. This might be the reason why you can see some try...catch blocks with just logging code inside.
If you want to get rid of exception handling code in your business logic, you might introduce an interceptor which will react appropriately upon particular exceptions.
HTH!
Firstly, you can and must log the exception stack trace of all exceptions. In fact, IMO if you only log that an exception happened you might as well not log it at all. However, very often what this leads to is a relaxed view of exceptions. What you should strive for is to have 2 log files or one specific category that if exceptions are in that category they mean something critical happened and must be addressed. Even if that means logging the same exception many times. Rather too many than not at all.
Secondly, it's fine to change all exceptions to checked exceptions - the majority of exceptions are not "recoverable". What I have done that worked well is simply wrap all transactions in an exception handling wrapper which logged the exception, then I can guarantee that all exceptions are logged. Furthermore, create a bunch of exception classes that extend runtime exception - this is much better than rethrowing exceptions as runtime exceptions as very often the inner exception stack trace is not logged in full when you wrap exceptions.
And thirdly, it is important to create a mechanism to map exceptions that do filter through to the front end with the back end cause. This is challenging but it's quite important. Errors that the user sees are far easy to track down if you can map them back to an exception stack trace in the log file.

Catch Exception high in the call stack- when dealing with n tiers?

Say I have 3 tier app- frontend domain and data access. I have read that it is a good idea to catch exceptions high in the call stack...so if I get a data-access exception, the domain layer merely does a finally, like so
try{
}finally{
//cleans up
}
and lets the data-access exception percolate to the frontend layer. Does this not break layering by making the front-end layer deal with the innards ? I think that each layer should either handler or wrap and throw exception that it cannot handle to its calling layer...
any thoughts ?
Lots of good feedback so far, I'll give you my take.
Rule #1. ONLY catch exceptions you are going to actually handle. By handle, I mean handle in such a way that the client's request can continue. You may catch things long enough to log information (don't abuse this, usually the stack is enough information) or to convert to a different error that propagates easier (ala Runtime based). But, if you can't handle it, don't bother catching it. That's just extra code that is useless and confusing. Even when you log or convert, you end up rethrowing.
Realize that most of the time, you can NOT handle an exception. Truly. Many fail to grasp this. But the reality is, if you get an IOException reading or writing to the disk, game over. That request cannot be completed for the user. If your network is flaky and you can't talk to the database, same thing.
Rule #2. When you do get an exception that you cannot handle, the only thing you can do is try to fail in such a way that it is helpful to the user. This means, log it for later analysis (including original stack/cause), and then report something as helpful as possible to the user. Clean up whatever you must, so that the system remains in a consistent state.
Given that this communication with the end user happens at a very high level, that means you usually have to catch at that level. Most of the time, I find that there is very little value in any exception handling between it's inception point and the top level where you catch it for logging and reporting to the user. I often convert to a form of RuntimeException, but that's only done to ease propagation through the layers.
The biggest and most important thing is to realize that you usually can't handle exceptions, so any code you write for them should be as simple as possible.
I don't think layering is such a pure idea that this breaks it.
Wrapping and rethrowing doesn't add much value either.
What's wrong with having the service layer handle exceptions? That ought to be the end of the line, the last line of defense. This design lets the service log the exception - once and for all - and send a user friendly message to the UI for display.
You generally want to catch exceptions higher in the call stack, but only to the point that is makes sense. If the data level can handle and log the exception and just pass a message back to the front-end then that will keep things simple and more flexible.
Personally, if I need to have a try and a finally then I would like to also catch and do something about the situation there rather than pass it up to the caller. Just keep in mind there are always exceptions to good design rules (normally another rule like KISS).
There are three interlocking problems here.
First, constantly re-wrapping exceptions can be done but what value is it providing? You are just creating more layers around the original exception. I only wrap an exception when I can provide additional information about the exception or when the first exception causes another.
Second, the idea of an exception is to respond that a function can not be completed normally. You should catch the exception at the place where it makes the most sense to deal with the problem. If the code has "another alternative" the exception should be trapped at that point. Otherwise log it for the user or developer to work out.
Third, the try/finally block. These are useful when an exception would cause resources to hang out in a open or allocated state. I always use try/finally to clean up resources that might be left open (my favorite is the Statement/ResultSet from java.sql, a huge memory hog). A really good programmer has a lot of this in their code as a way to recover gracefully without creating huge memory leaks or resource constraints.

Question about Java.lang.Error

There are lot of posts on java.lang.Error saying it should not be caught. My question is if it should not be caugth the what is the use of it. Since it is Throwable so we can catch it in try catch. I read some posts like only in some situation it should be caught, how to know these situations.
In short i want to know what can go wrong when i catch Error. What is process behind it. Why they have made Error and its Subclasses? If my app is not supposed to catch them then what catches them? Why my code cannot handle this caught Error? If i simply catch one Error and write some handling code in Catch block, won't that code run?
An Error (especially a subclass of VirtualMachineError) indicates that the JVM has encountered an internal issue - one that means that its internal state may no longer be consistent. If you catch an Error and attempt to recover, future behaviour is undefined. The reason that errors are Throwable is so they can be thrown - eg you may do it your self for errors in a native library that can't be recovered from (eg the library could have written to JVM memory, or corrupted its internal static state). The same stack walking and stack trace producing machinery is used in the case of all Throwables - it would be silly to have another mechanism to do the same thing.
Most errors in the JVM that are not VirtualMachineErrors are situations where a native library could have corrupted its static state - eg AWTError, ZipError.
However there are some rare cases where catching an Error is sane: AssertionError in a testing framework, and LinkageError where you have to deal with the absence / presence of different versions of libraries at runtime. This is a pretty rare requirement and may be better handled through reflection.
All rules have exceptions (except this one).
Even if everybody say you should not, there are plenty of cases where it's totally appropriate to catch those java.lang.Error. The logic behind the rule was: "do not try to continue running your application after a fatal condition was detected". You therefore must be careful before doing something after such an error is thrown. It is possible that the system might not be able to continue its task afterward.
It might be OK for a servlet to catch OutOfMemoryError, log the error and destroy the session. Maybe the problem was with that precise session. Destroying it would restore the memory and allow other users to continue using the system. However, you should have a mechanism to track those errors in real-time in order to:
Fix programming errors
(AssertionError, StackOverflowError)
Fix configuration errors
(UnsatisfiedLinkError)
Correct JVM sizing parameters (OutOfMemoryError)
This kind of handling should be done very "high" in the call stack (i.e. near the main()), where the main loop (or equivalent) is performed. I think it's not a good practice to catch Error in deep code, you should at least rethrow the error in those cases.
Similar question already answered here - When to catch java.lang.Error?
Basically, you should never attempt to catch it as its thrown on fairly serious issues like when your thread has dead for some reason, and is not recoverable.
There are however sometimes the need to catch the error when dealing with the framework itself as stated in the above URL.

Categories

Resources