When is throwing/catching general exception acceptable - java

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.

Related

Catching Exceptions - why is it necessary?

Suppose I have this trivial piece of code, and at runtime list size is 4.
try{
for(int i = 0; i < list.size(); i++){
list.get(10);
}
}catch(NullPointerException e){
System.out.println(" exception to string :" + e.toString());
System.out.println(" exception get class" + e.getClass());
e.printStackTrace();
}
So the JVM will throw an index out of bounds exception, without having to implement this in the catch block.
Similarly, if the list is null, the JVM would throw a null pointer exception.
So with that said, why bother to declare an IndexOutOfBoundsException or NullPointerException at all? Why not just declare a generic Exception at the catch block ? What is the advantage and disadvantage to this approach?
Usually, you shouldn't catch a generic exception somewhere down in the code because it often indicates a bug in your code which you have to fix.
Some checked exceptions (like IOException) which are related to external resources are not within your control, so you should catch them and react to them, but NullPointerExceptions or IndexOutOfBoundException should be avoided by checking the object beforehand.
As you surely know there are basically two types of exceptions: checked and unchecked. You need to declare or catch checked exceptions but don't have to do that for unchecked ones.
So what's the difference? It often depends on who uses them but generally it's like this:
Checked exceptions are thrown for things that are expected to go wrong eventually, e.g. IOException etc. - a file not being available (not existing, locked etc.) or writable isn't something that never happens and that the developer can try to prevent. Since you have to expect those things to go wrong you'll use a checked exception to either force the method signature to declare those things can go wrong or to catch the exception and handle the case.
Unchecked exceptions are mostly used for things that can but should not go wrong. In many cases those are due to programming errors (such as NullPointerExceptions, IndexOutOfBoundExceptions etc.) or unexpected system failures (database not available etc.). You normally don't catch them explicitly since they're not expected anyways.
That being said there are situations where checked or unchecked exceptions are used for something else (e.g. in libraries that need to rely on being able to bubble up a multitude of exceptions and thus wrap checked exceptions un unchecked ones).
As for the catching/declaring in the signature: you'll normally want to be as explicit as possible with checked exceptions, i.e. you might want to handle an IOException differently than let's say an SQLException. Unchecked exceptions might be just caught and reported (e.g. by logging or rethrowing them) but even in those cases you might want to catch some explicitly, e.g. EJBExceptions which are thrown by EJBs and which might just be a wrapper for an actual checked exception and thus you might want to unwrap those.
A final word on NullPointerException: you'll probably never want to catch those explicitly since they shouldn't occur in the first place (either make sure nothing is null or check before accessing those things) and often there are so many things that could be null in a try-block (directly and in the methods that are called) that you'd have a hard time to implement a reasonable reaction. In those cases it's best to just catch any unhandled exception (as is done for threads anyways) and report them to the developer so they can have a look and fix the problem.
In order to understand why you may want to use more specific exceptions in your catch block instead of just the generic Throwable (which means EVERYTHING that can possibly go wrong), you may want to consider what it is that is going on here.
When creating software that is to be run in production for years, you need it to be very, very robust. This mean that you want your code to be able to handle any situation gracefully, and keep running even though something went wrong.
In the particular code you are showing it might very well be that it is perfectly acceptable that the list is too short (a library that occasionally misbehaves) but it is a fatal and unforeseen error if list is null.
The simplest way to differentiate is to use the way that the exception hierarchy is designed, and have different catch-blocks.
Also, if you use Java 7 or later, you can create a combined catch block using a pipe sign which allows you to retain the original exception even if the handling code is the same.

Any Work around for not using a broader Exception, the "System.Exception"?

I am a fresher, and after successfully completing my project I scanned it through fortify. it gave me a list of issues, out of which just one categories remain. (Fortify a code quality scanning tool)
it says, "Not to use Broader Exception i.e. System.Exception" to catch exceptions unless in some conditions.
But I have a few methods that have 25-30 lines of code with different types of operations, in such case how to figure out which all specific exceptions to catch.
Should we also throw all these exceptions to be caught at a higher level catch, as i read "throw first catch late".
Please suggest me a clean way to do this.
e.g.
public SomeMethod(arg) throws IOException,SQLException,beanNotFoundException {
try {
someCode
} catch (IOException|SQLException|beanNotFoundException ex) {
logger.log(ex);
throw ex;
}
}
But also if i don't use Exception Class altogether till the end, i also have to make sure that I am not missing any exception to handle.
Is there a better approach.
Static Analysis
First and foremost, let me start with a little fallacy that most people fall subject to (and I see a lot in the corporate world): Static analysis tools are not infallible. They make mistakes. There are some warning classes that, with all the computing power known to man and with the remaining lifespan of the universe, the tool may not be able to exhaustively analyze a piece of code related to a particular warning class. Moreover, there are some warning classes that can complete before the end of time, but would be unreasonable to expect you to wait 7 days for an answer for one warning on one section of code for one execution path. That is, static analysis tools have to make guesses sometimes. The better tools are better at making guesses (you pay for what you get), but in the end, they are all capable of guessing right (true positive/negative) or wrong (false positive/negative).
Additionally, some warning classes may be applicable and some may not be. Some other warning classes may be important to you and some may not be. For example, PMD has a warning class to the effect of "Unused Import". An unused import has no effect on runtime, and while it may not be ideal, you can leave it in your code and it will not affect you unless your codebase is large and requires time to compile, and you have lots of these (unused imports make it longer to build your project). I particularly mention static analysis, because it sounds like you ran Fortify on your codebase and fixed anything and everything without questioning the validity. Most of the time it will probably be right, but just don't take it as fact because it told you so. You need to question whether these tools are always right.
Your example
So your example is not a false positive. If you do
throw new Exception("");
that's generally not what you want to do. It's fine for debugging and just quickly throwing code together. But, as your codebase gets larger, handling Exceptions will get more difficult.
This leads me right into my next point. You make the statement
But I have a few methods that have 25-30 lines of code with different types of operations, in such case how to figure out which all specific exceptions to catch.
...
But also if i don't use Exception Class altogether till the end, i also have to make sure that I am not missing any exception to handle.
Which seems to indicate to me that you either have something to the effect of
try{
//25-30 lines of code
} catch (Exception ex) { /*ex.printStackTrace(); Logger.getLogger(...).log(...); etc etc...whatever it is you do here, or maybe nothing at all*/
This is pretty bad - in most cases.
To get back to answering your question before I explain why, yes, you should absolutely catch each individual exception. The reason for this, and why your catch all is bad, is because if there is something specific that goes wrong, you can't have a specific type of error handling.
For example, take a function Foo#bar(java.lang.String), which throws an IOException when a disk access fails because you tried to write to a bad file, a BooException if you pass in a String without a special character in it, or a BazException for some other arbitrary reason. Now let's go back to your example from above: what if I wanted to realize that the file I was writing to was bad, and maybe prompt the user for some clarification before I moved on? What if I knew that if a BooException was thrown, that the user should have never been here in the first place, and I need to redirect them to some location? What if I knew that when a BazException that the system was out of sync with some other system and that this is a fatal problem, and now I need to do resource cleanup before I forcefully crash the JVM?
The above reasons are why you should do individual try/catch blocks for each statement and each exception.
That being said, there are reasons to not do this. Imagine, with the above example, that all you want to do for a IOException, BooException and BazException (and also any runtime exceptions, i.e. NullPointerException) that I just want to log the exception and move on. In this case, I would say it's OK to do a try/catch around a block of code - so long as it's just around the code that this applies to.
EDIT: You made a point about missing an exception, but putting a response to that in the comments seemed unruly to look at. In any case, let me start off by saying if it is not a runtime exception, then you will not even be able to compile without handling it. Catching Exception catches everything, runtime or not, which is how you compile now. From my example above, if there are runtime exceptions you are worried about missing, instead of just starting off with catching Exception:
Foo myFooInstance = new Foo();
String someValue = "value";
try {
myFooInstance.bar(someValue);
} catch (IOException ioe) {
/*handle file access problem*/
} catch (BooException boe) {
/*handle user in wrong spot*/
} catch (BazException bze) {
/*handle out-of-sync fatal error*/
} catch (Exception ex) {
LogRecord lr = new LogRecord(Level.SEVERE, "Unhandled exception!! returning immediately!!");
lr.setThrown(ex);
lr.setParameters(new Object[]{someValue});
Logger.getLogger(MyClass.class.getName()).log(lr);
return;
}
Here you end with your catch-all rather than starting with it. Think of it as your last-ditch effort to try to handle everything. It may not mean the exception is fatal to your program, but you probably shouldn't continue either (hence why my example uses return;)
Another small thing to consider, is that it becomes exponentially more difficult for the JVM to catch the exception properly the larger the try block gets (if the exception is never thrown, there is no overhead). This is more trivial to powerful machines, but something to keep in mind. With that in mind, I also don't have any sources for performance about exceptions being thrown in large try blocks, so take that with a grain of salt unless somebody finds something and mentions it.
In general, you only need to worry about handling/throwing checked exceptions. A clean way to write the method depends on the code base and structure of your application. Here are some alternatives:
If you want the client code (code calling someMethod) to handle the exception, you can do this:
public void someMethod(String arg) throws IOException, SQLException,
BeanNotFoundException {
doSomething(arg);
}
If you can handle the exception locally in someMethod, do so, but do not rethrow the same exception up in the call stack:
public void someMethod(String arg) {
try {
doSomething(arg);
} catch (IOException | SQLException | BeanNotFoundException ex) {
logger.log(ex);
handleException(ex);
}
}
If the exception is something you cannot recover from, and you don't want to enforce client code to handle the exception, you can wrap it as a RuntimeException. This will potentially terminate the program (which is usually what you want when a fatal error occurs):
public void someMethod(String arg) {
try {
doSomething(arg);
} catch (IOException | SQLException | BeanNotFoundException ex) {
logger.log(ex);
throw new RuntimeException(ex);
}
}
For a good explanation about checked vs. unchecked exceptions, you can refer to Java: checked vs unchecked exception explanation.
My advice would be to ignore what Fortify is saying. Or better still, figure out how to selectively suppress these warnings.
The alternative to your current version that Fortify is suggesting is objectively bad in most contexts. Your current version is not bad, only (a bit) verbose.
Another alternative would be to wrap the exceptions in a custom exception or exceptions that have a common custom checked exception as the base-class (NOT Exception or Throwable or RuntimeException). That could make code like you example neater, but it means that you need to add code (somewhere) to do the wrapping and (maybe) unwrapping. In short, that's no idea too.
OK so what is the problem with catching Exception? Well basically, it catches everything ... including any unexpected uncheck exceptions that are evidence of bugs. If you then declare the method as throws Exception it only gets worse.
I have seen an example (no names) where someone did this in a large Java product. The result is that the product's Java APIs are horrible to program against. Every non-trivial API method is declared as throws Exception, so someone programming against the APIs has no idea what to expect. And the code-base is proprietary and obfuscated. (And the worst thing is that the lead developer still thinks it was a good idea!)
What about wrapping the exceptions in RuntimeException? That's not quite as bad1 as Exception but the problem is that the programmer still can't tell what exceptions to expect.
1 - It is not quite as bad in the sense that throws Exception is effectively "noise" once you have gone done the path that anything can throw anything.
The general rule of thumb is that checked exceptions are thrown for errors that are external or unpredictable, and which the caller can reasonably be expected to do something about, even if that only means displaying a message to the user. Whether you catch them or pass them up the call stack depends on where it makes the most sense to handle them.
Unchecked exceptions are thrown for unsatisfied preconditions or invalid arguments. In other words, the programmer screwed up. That's why you're not forced to catch them; they're typically things that "shouldn't happen." You generally don't need to worry about them if you're using the API correctly. The only time you should catch unchecked exceptions is when an API doesn't follow these conventions and throws unchecked exceptions for external or unpredictable reasons.

Re-throwing RuntimeExceptions after catching Checked Exceptions [duplicate]

This question already has answers here:
What issues may ensue by throwing a checked exception as a RuntimeException?
(6 answers)
Closed 9 years ago.
In Java it is observed that there is a convention of re-throwing a RuntimeException just after handling a Checked Exception.
This way has both good and bad consequences. When the compiler forces something to be handled via a Checked Exception, the developer can just get rid of it by catching it and re-throwing it as a RuntimeException.
Can someone explain if this scenario can be considered as a good practice? If so, would this approach be less error prone or would it make the code base unstable?
Actually it is the incompetent attempts at handling checked exceptions which result in an unstable code base. Typically, you'll have this:
try {
//stuff
} catch (IOException e) {
log.error("Failed to do stuff", e);
throw e;
}
and then next level up you'll have to deal with it again, typically logging it all over and making a mess of the log files. It will be even worse if you don't rethrow:
try {
// do stuff
} catch (IOException e) {
return null;
}
Now the calling code has no idea something went wrong, let alone what. Compared to those attempts, this actually accomplishes exactly what the application logic needs:
try {
// do stuff
} catch (IOException e) {
throw new RuntimeException(e);
}
Now the exception can freely propagate up the call stack until it reaches the well-defined exception barrier, where it:
aborts the current unit of work;
gets logged at a single, unified spot.
In a nutshell, to decide whether to catch-and-handle or catch-and-rethrow, just ask yourself this question:
Must the occurrence of this exception abort the current unit of work?
if yes: rethrow an unchecked exception;
if no: provide meaningful recovery code in the catch-block. (No, logging is not recovery).
From many years of real-life experience I can tell you that more than 90% of all possible checked exceptions are of the "aborting" type and need no handling at the place of occurrence.
Argument against the language feature of checked exceptions
Today, checked exceptions are widely recognized as a failed experiment in language design, and here's the key argument in a nutshell:
It is not up to the API creator to decide on the semantics of its exceptions in the client code.
Java's reasoning is that exceptions can be divided into
exceptions resulting from programming errors (unchecked);
exceptions due to circumstances outside of programmer's control (checked).
While this division may be real to some extent, it can be defined only from the perspective of client code. More to the point, it is not a very relevant division in practice: what truly matters is at what point the exception must be handled. If it is to be handled late, at the exception barrier, nothing is gained by the exception being checked. If handled early, then only sometimes there is a mild gain from checked exceptions.
Practice has confirmed that any gains afforded by checked exceptions are dwarfed by real-life damage done to real-life projects, as witnessed by every Java professional. Eclipse and other IDEs are to blame as well, suggesting inexperienced developers to wrap code in try-catch and then wonder what to write in the catch-block.
Whenever you encounter a method which throws Exception, you have found yet another living proof of the deficiency of checked exceptions.
The idea of checked exceptions is "Java only" - as far as I know, no language after Java adopted this idea.
There are too many checked exceptions which are caught ... and silently ignored.
If you look at Scala, they dropped it as well - it's only there for Java compatibility.
In this tutorial on Oracle's web site, you will find this definition:
If a client can reasonably be expected to recover from an exception, make it a checked exception.
If a client cannot do anything to recover from the exception, make it an unchecked exception.
This notion has been adopted in Scala as well, and it works fine.
Technically speaking your proposal works. Discipline and code reviews are required in either way.
The term "can just get rid of it" is not totally correct in this case. This is getting rid of exceptions:
try {
} catch (Exception e){
e.printStacktrace();
}
This is the most common bad practice among the try-catch use. You are catching the exception and then, just printing it. In this case, the catch block catches the exception and just prints it, while the program continues after the catch block, as if nothing had happened.
When you decide to catch a block instead of throwing an exception, you must be able to manage the exception. Sometimes exceptions are not manageable and they must be thrown.
This is something you should remember:
If the client can take some alternate action to recover from the
exception, make it a checked exception. If the client cannot do
anything useful, then make the exception unchecked. By useful, I mean
taking steps to recover from the exception and not just logging the
exception.
If you are not going to do something useful, then don't catch the exception. Re-throwing it as a RuntimeException has a reason: as stated before, the program just cannot continue as nothing happened. This way, a good practice would be:
try {
} catch (Exception e){
//try to do something useful
throw new RuntimeException(e);
}
This means: you just caught an Exception (like an SQLException) from which you can't recover without stopping and resetting the thread. You catch it, you try to make something in between (like resetting something, closing open sockets, etc...) and then you throw a RuntimeException().
The RuntimeException will suspend the whole thread, avoiding the program continue as if nothing have happened. Furthermore, you were able to manage the other exception without just printing it.
It may or may not be okay, depending on the context, but it probably is not.
As a rule of thumb RuntimeExceptions should only be used to indicate programming errors (examples include IllegalArgumentException and IllegalStateException). They don't have to be checked exceptions because you generally assume your program is correct until proven otherwise and you cannot handle these exceptions in a meaningful manner (you have to release an updated version of the program).
Another valid use of runtime exceptions is when you use a framework that will catch and handle the exception for you. In such a scenario it would only be burdensome to having to declare the exception in every method when you are not going to handle it anyway.
So generally speaking I would say re-throwing a checked exception as a runtime exception is very bad practice unless you have a framework that will handle it properly.
The general rule is: you throw a checked exception when the caller might be able to do some kind of recovery when informed about it. Otherwise, throw an unchecked exception.
This rule applies when an exception is first thrown.
But this also applies when you catch an exception and are wondering whether to throw a checked or unchecked exception. So there is no convention to throw a RunTimeException after catching a checked one. It is decided in a case-by-case basis.
One small tip: if you are going to just re-throw an checked exception after catching one and do nothing else, most of the time it is alright to just not catch the exception and add it to the exceptions thrown by the method.

Guidelines on Exception propagation (in Java)

Are there any guidelines on exception propagation in Java?
When do you add an exception to the method signature?
For example: if an exception is only thrown when an essential program resource is missing, and can only be handled at the top level, do I propagate it through all methods using this exception through all the methods using the erring method?
Are there any good practices? Any bad practices?
I'm sorry if I'm being vague, but I'm just looking for some (general) advice on programming style concerning exceptions.
Guidelines that have helped me in the past include:
Throw exceptions when the method cannot handle the exception, and more importantly, should be handled by the caller. A good example of this happens to present in the Servlet API - doGet() and doPost() throw ServletException or IOException in certain circumstances where the request could not be read correctly. Neither of these methods are in a position to handle the exception, but the container is (which results in the 50x error page in most cases).
Bubble the exception if the method cannot handle it. This is a corollary of the above, but applicable to methods that must catch the exception. If the caught exception cannot be handled correctly by the method, then it is preferable to bubble it.
Throw the exception right away. This might sound vague, but if an exception scenario is encountered, then it is a good practice to throw an exception indicating the original point of failure, instead of attempting to handle the failure via error codes, until a point deemed suitable for throwing the exception. In other words, attempt to minimize mixing exception handling with error handling.
Either log the exception or bubble it, but don't do both. Logging an exception often indicates that the exception stack has been completely unwound, indicating that no further bubbling of the exception has occurred. Hence, it is not recommended to do both at the same time, as it often leads to a frustrating experience in debugging.
Use subclasses of java.lang.Exception (checked exceptions), when you except the caller to handle the exception. This results in the compiler throwing an error message if the caller does not handle the exception. Beware though, this usually results in developers "swallowing" exceptions in code.
Use subclasses of java.lang.RuntimeException (unchecked exceptions) to signal programming errors. The exception classes that are recommended here include IllegalStateException, IllegalArgumentException, UnsupportedOperationException etc. Again, one must be careful about using exception classes like NullPointerException (almost always a bad practice to throw one).
Use exception class hierarchies for communicating information about exceptions across various tiers. By implementing a hierarchy, you could generalize the exception handling behavior in the caller. For example, you could use a root exception like DomainException which has several subclasses like InvalidCustomerException, InvalidProductException etc. The caveat here is that your exception hierarchy can explode very quickly if you represent each separate exceptional scenario as a separate exception.
Avoid catching exceptions you cannot handle. Pretty obvious, but a lot of developers attempt to catch java.lang.Exception or java.lang.Throwable. Since all subclassed exceptions can be caught, the runtime behavior of the application can often be vague when "global" exception classes are caught. After all, one wouldn't want to catch OutOfMemoryError - how should one handle such an exception?
Wrap exceptions with care. Rethrowing an exception resets the exception stack. Unless the original cause has been provided to the new exception object, it is lost forever. In order to preserve the exception stack, one will have to provide the original exception object to the new exception's constructor.
Convert checked exceptions into unchecked ones only when required. When wrapping an exception, it is possible to wrap a checked exception and throw an unchecked one. This is useful in certain cases, especially when the intention is to abort the currently executing thread. However, in other scenarios this can cause a bit of pain, for the compiler checks are not performed. Therefore, adapting a checked exception as an unchecked one is not meant to be done blindly.
You should handle the method as soon as possible, but it must make sense. If the exception doesn't make sense to be thrown by your method, but you can't handle it, wrap it into another exception and throw this new exception.
A bad practice about exception is to catch them all (it's not pokemon, it's java !) so avoid catch(Exception e) or worse catch(Throwable t).

Re-throwing exceptions in Java

In java there is a possibility of re-throwing the exception but there is any advantage in it?
One example of when you want to rethrow an exception is when you don't really know how to handle it yourself, but you'd like to log that the exception was thrown. Rethrowing it allows you to both capture the stack information that you need to log, and pass the exception up the call stack for the caller to handle.
Sure. If you need to perform some special processing (logging, clean up, etc) for the exception, but can't "handle" it completely, it is common to do the processing and then rethrow the exception. Note, that in many cases (especially cleaning up resources) you probably want a finally clause rather than a catch/rethrow.
Sometimes, you want a specific type of Exception to be thrown by a method, but there are rare instances that cause other Exceptions to be thrown within the method. I often wrap the causal Exception with my desired Exception and then rethrow the desired Exception.
This is really useful when you can't determine that the Exception has caused your operation to fail until control is passed to the calling method (or one of its ancestors), since if the process does eventually fail, I can trace back in the stacktrace to see why.
I haven't done Java in years, but from what I remember it's just like other languages with exceptions and OO. Exceptions can be subclassed, and often, you'll want to catch a base class of many exceptions, but might not be able to handle all of them. So say you're handling a remote file transfer, and want to catch all IOErrors, because you handle most of them, but not DiskFull. You can rethrow that, and let someone else deal with it further up the chain, but deal with the other issues, like TransmissionFailed, by re-doing the transmit.
If you can somehow justify that you need to re-throw the same exception that you caught, I'd argue that there is something wrong with your design.
Catching one exception and re-throwing another makes perfect sense. For instance, you may want to add detailed information that the original exception did not have.
Real World Cases
Here are some real world situations in which I needed to rethrow java exceptions:
When doing JDBC call, I would catch a SQLException. However, postgres would throw a PSQLException with additional data and status. In testing edge cases we were able to corrupt the database and we wanted the logger to have very specific data on the exception and state. We would wrap the original exception in a new exception with more data regarding the server state and rethrow.
When implementing a text parser, I would want to catch a number of runtime parsing exceptions such as NumberFormatException and pass them up the stack with additional data on what text caused and the source of the text that caused the parsing exception.
My coworker told me of a project in which he worked where every exception was wrapped in another exception of one of two types - RetryableException and FatalException. In the case of a Retryable exception, the application would wait and retry the operation after a fixed period of time. I'm not exactly sure about how I feel about this design, but I can see it as a stop-gap for dealing with some transactional issues.
In some cases I would be using an existing API that had a throws defined for a high-level exception and I would be doing an operation that would throw an unrelated exception (that I felt really belonged as a RuntimeException) - I then would rethrow the exception as the cause of the more general exception.
The most pure case that I can think of in which you may want to rethrow an exception is when you want to add additional data to it. For example:
public bizMethod() throws CoolBizLogicException {
int policyId = getPolicyId("bar");
try {
coolBizLogic(foobar); // this throws an exception
}
catch (CoolBizLogicException cble) {
cble.setPolicyId(policyId);
throw cble;
}
}
I don't think so. If you can't handle it, don't catch it.

Categories

Resources