I have a very basic question about best practice of using try/catch.
I have a simple function (DAO) like this:
public void addVehicle(Vehicle vehicle) {
em.getTransaction().begin();
em.persist(vehicle);
em.getTransaction().commit();
}
and using DAO function inside web service:
#WebMethod(operationName = "addVehicle")
public void addVehicle(Vehicle vehicle) {
try {
vehicleDAO.addVehicle(vehicle);
System.out.print("Vehicle added");
} catch (Exception e) {
e.printStackTrace();
}
}
OR is better using try/catch inside DAO function like this:
public void addVehicle(Vehicle vehicle) {
try {
em.getTransaction().begin();
em.persist(vehicle);
em.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
}
}
There is no perfect rule for that.
Often code is clearer and less complex if exceptions are catched as early as needed, but as late as possible.
You should think who has to take an action when that Exception happens, this decides if you catch it inside the method (addVehicle) or if you throw it such that the caller has to catch it.
E.g:
public void addVehicle(Vehicle vehicle) throws SQLException{
em.getTransaction().begin();
em.persist(vehicle);
em.getTransaction().commit();
}
In this example the caller has to catch.
Further only in few situations you should catch Exception or RunTimeException, better
catch that specific Exception, like IOException instead of Exception.
Somewhere in your code you will need a "last line of defense" where it make sense to catch (Exception ex). This is needed to handle errors that should not happen.
When deciding where to handle a specific kind of exception, the best rule of thumb is to stop looking at the micro details of your code, take a step back to reason about your program's logic and consider these things:
Is the exception something that your program's current operation cannot recover from? If yes, it only makes sense to put the exception at the topmost level of that operation, to ensure that it doesn't continue.
If your program can work around that particular exception (perhaps by trying something else before giving up), take each layer of nested functions (starting from the highest) and each time ask yourself: If the exception occurs during the execution of some line of code in this function, would it make sense for this function to continue? As long as the answer is "yes", move to the deeper level. As soon the answer is "no", chances are this is the best place to put the handler for that exception.
Alternatively to the previous one, you could decide what would your program's alternate "plan of attack" be in case the exception is raised. Then, go to the line of code that would raise that exception and ask yourself: Does this function have enough context information to perform the workaround I have in mind? As long as the answer is "no", move to the caller function. As soon as the answer becomes "yes", consider putting your exception handler there.
That being said, you should only catch reasonably specialized exceptions and keep the catch(Exception ex) construct only as a last resort only at the top level and only after all the other possible catch blocks, reserving it only for kinds of exceptions you really couldn't predict at the time of writing. (I know you said this is not the point of the example, but since we're at it, I thought it should be mentioned to make this answer more complete.)
You should only catch those exceptions which you want to handle. You may include a topmost exception handler to turn any unhandled exceptions into something somewhat useful for the end user.
Instead of e.printStackTrace();, try return proper exception message.
find out more about exception handling here
Here is more discussion about exception handling.
AFAIK the best practice will be smth like that:
public void addVehicle(Vehicle vehicle) {
em.getTransaction().begin();
try {
em.persist(vehicle);
em.getTransaction().commit();
} catch (Exception e) {
if (em.getTransaction().isActive()) {
try {
em.getTransaction().rollback();
} catch (Exception e) {
// Log rollback failure or something
}
}
throw new RuntimeException(e);
}
}
Use both, the only reason is to use catch RuntimeException or even Throwable. Because this kind of exception is typically thrown by the underlying frameworks. An you should catch exactly this kind of exception if you want to make some actions, for example logging, print stack trace, etc., before you re-throw it again. If you don't do in such way you may loose the cause of exception.
#Transactional
public void addVehicle(Vehicle vehicle) {
try {
//do whatever with session
} catch (RuntimeException e) {
e.printStackTrace();
throw new Exception(e);
}
}
Related
Imagine some code:
public void doSomething(Object object){
try {
if (object == null)
throw new BusinessException("Object was null");
try {
// do logic actions
} catch (Exception e) {
throw new BusinessException("Something went wrong doing logic", e)
}
try {
// do some IO actions
} catch (Exception e) {
throw new BusinessException("Something went wrong doing IO.", e)
}
} catch(Exception e){
throw new BusinessException("Something went wrong in doSomething.", e)
}
}
The BusinessException is an extension of RuntimeException. I'm told by my manager and another senior engineer that BusinessException is the only exception that should ever get thrown and every method should be designed like the above method to ensure that. Anytime something goes wrong they want the same BusinessException thrown.
They idea is that they want to "abstract" away logical exceptions from the user and only provide "business exceptions" to the user. My manager does not want us to only catch specific exceptions, e.g. IOException They want to always catch(Exception) to make sure nothing is missed.
I don't understand this "abstraction" they are talking about. I'm pretty sure nothing is being "abstracted" away, an exception is just being encapsulated (or masked) in a new exception.
Semantics aside, I find this truly bizarre and I'm struggling to understand the value they think this verbose exception handling provides. It is not hard for me to imagine how this can make debugging more difficult. If any business exception gets thrown it immediately gets caught by another catch block and re-wrapped into a new exception, complicating the stack trace and potential debugging efforts.
It also seems like a performance issue to have so much exception instantiation.
Further, this is a spring boot application and we already have a ResponseEntityExceptionHandler
#ControllerAdvice
public class MyAppResponseEntityExceptionHandler extends ResponseEntityExceptionHandler{
#ExceptionHandler(value = { IllegalArgumentException.class })
protected ResponseEntity<Object> handleConflict(IllegalArgumentException ex, WebRequest request) {
String bodyOfResponse = "Check the arguments";
return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.CONFLICT, request);
}
// Several more for different exception types...
}
Is this just a "to each their own" situation or is this objectively a problem?
First of all, it's never recommended to have a generic catch block that catches and instance of Throwable or Exception, unless it exists in a chain of catch blocks, for example:
public void doSomething() {
try {
// do some database stuff
} catch (SQLException e) {
throw new BusinessException("something went wrong with database", e);
}
try {
// do some IO stuff
} catch (IOException e) {
throw new BusinessException("something went wrong with IO");
}
}
Now anything other than those two exceptions shouldn't be caught, since it's not the responsibility of this particular function, function should only complain about errors that are relative to what they do.
as a caller I might do something like this:
SomethingDoer s = new SomethingDoer();
s.doSomething();
now if I'm worried that an exception might get thrown unexpectedly, it's my responsibility as a caller to handle it, so the API deligates the uncaught exception for the caller to handle, like so:
SomethingDoer s = new SomethingDoer();
try {
s.doSomething();
} catch ( BusinessException e) {
LOGGER.error(e.message) // prod logging
LOGGER.debug(e) // debug logging with stacktrace
// hypothetical error listener
errorListener.onError(e);
//handle or log, but not rethrow.
} catch (Exception e) { // cringe..
LOGGER.error("something went wrong, unexpectedly"); // prod logs
LOGGER.debug("something went wrong, unexpectedly", e); // debug logs with stacktrace
/* logged AND rethrown since up till this point all expected
exceptions should be wrapped and rethrown or logged,
so if we get here its a fatal error, and you need to interrupt the application*/
throw e;
The latter - cringe looking - catch( Exception e) block is also not recommended and the exception should be propagated up the stack to the main thread, Checked Exceptions are usually handled that way.
So language specific exceptions - internal - should be caught and wrapped in a BusinessException even before reaching the ControllerAdvice handler and this handler - since it is relatively close to the view layer of the app should only handle business specific exceptions and not internal exceptions.
Your manager and senior engineer may be considering Effective Java. From the third edition, Item 73: Throw exceptions appropriate to the abstraction.
It is disconcerting when a method throws an exception that has no apparent connection to the task that it performs. This often happens when a method propagates an exception thrown by a lower-level abstraction. Not only is it disconcerting, but it pollutes the API of the higher layer with implementation details. If the implementation of the higher layer changes in a later release, the exceptions it throws will change too, potentially breaking existing client programs.
To avoid this problem, higher layers should catch lower-level exceptions and, in their place, throw exceptions that can be explained in terms of the higher-level abstraction. This idiom is known as exception translation.
Perhaps your manager is being overzealous with this bit of advice. Effective Java goes on to caution,
While exception translation is superior to mindless propagation of exceptions from lower layers, it should not be overused.
You may be justified in pointing out this overuse to your manager, but I suspect persuasion will be difficult. You can take some solace in Item 72: Favor the use of standard exceptions. I personally prefer that advice, and tend to avoid creating custom exceptions, but certainly other developers feel differently.
It is like, the end user doesn't know what to do with exception so a generic exception will be better.
You can write diff custom exceptions for diff type of operations, like Database calls, api calls and return only one type of exception to the caller.
i.e You can define you custom exception like this.
public class BusinessException extends RuntimeException {
private final ErrorCodes errorCode;
private final Object body;
public BusinessException(String message, ErrorCodes errorCode) {
super(message);
this.errorCode = errorCode;
this.body = null;
}
public BusinessException(String message, ErrorCodes errorCode, Object body) {
super(message);
this.errorCode = errorCode;
this.body = body;
}
}
Where ErrorCodes is the enum that will be having the ErrorCodes like InternalError, EntityNotFound, Unauthorised.
Now you can use this custom exception, you will catch any exception in the application and throw this exception with proper error message and error code.
Something like this.
throw new BusinessException("Error while fetching some api data.", INTERNAL_SERVER_ERROR);
or
throw new ServiceException("User is not authorised to perform operation.", UNAUTHORIZED);
Recently, I met some exception problem in java, which reminded me of the typical idiom recommended by Bruce Eckel:
Converting checked to unchecked exceptions
The real problem is when you are writing an ordinary method body, and you call another method and realize, "I have no idea what to do with this exception here, but I don’t want to swallow it or print some banal message." With chained exceptions, a new and simple solution prevents itself. You simply "wrap" a checked exception inside a RuntimeException by passing it to the RuntimeException constructor, like this:
try {
// ... to do something useful
} catch (IDontKnowWhatToDoWithThisCheckedException e) {
throw new RuntimeException(e);
}
This seems to be an ideal solution if you want to "turn off the checked exception—you don’t swallow it, and you don’t have to put it in your method’s exception specification, but because of exception chaining you don’t lose any information from the original exception.
This technique provides the option to ignore the exception and let it bubble up the call stack without being required to write try-catch clauses and/or exception specifications.
However, I found it didn't work in some cases. as seen here:
package exceptions;
// How an exception can be lost
class VeryImportantException extends Exception {
#Override
public String toString() {
return "A very important exception";
}
}
class HoHumException extends Exception {
#Override
public String toString() {
return "A trivial exception";
}
}
public class LostMessage {
void f() throws VeryImportantException {
throw new VeryImportantException();
}
void dispose() throws HoHumException {
throw new HoHumException();
}
public static void main(String[] args) {
try {
LostMessage lm = new LostMessage();
try {
lm.f();
} catch (VeryImportantException e) {
throw new RuntimeException(e);
} finally {
lm.dispose();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}/* Output:
Exception in thread "main" java.lang.RuntimeException: A trivial exception
at exceptions.LostMessage.main(LostMessage.java:36)
Caused by: A trivial exception
at exceptions.LostMessage.dispose(LostMessage.java:23)
at exceptions.LostMessage.main(LostMessage.java:33)
*///:~
As the output demonstrated, the second exception completely obliterates the first one. There is no record of the first exception in the exception stack trace, which can greatly complicate debugging in real systems. usually, it’s the first exception that you want to see in order to diagnose the problem.
Joshua Bloch recommends the try-with-resource way that a resource must implement the AutoCloseable interface, which process is somewhat complex.
So, my question is this: is there any way I can use to make sure that exception will not lose its stack trace information by Bruce Eckel's approach?
You might want to consider using try-with-resource instead of a finally block. It tends to handle this situation more like it sounds you would want the situation handled. See this article for more details.
Alternatively, you could simply eat the exception (as Andy Thomas's answer shows), or (if you want to know about both exceptions that were thrown) you could combine the exceptions into a single kind of Aggregate Exception.
The problem isn't that you're wrapping the exception. The problem is that you're replacing it with a subsequent, unrelated exception thrown from the finally block.
One easy way to avoid this is to not throw an exception from the finally block.
For example:
try {
LostMessage lm = new LostMessage();
try {
lm.f();
} catch (VeryImportantException e) {
throw new RuntimeException(e);
} finally {
try {
lm.dispose();
} catch ( HoHumException e ) {
// No-op or logging
//
// If we're exiting this try-finally because an exception
// was thrown, then don't allow this new exception to replace it.
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
How do I make it so the code runs only if there was no exception thrown?
With finally code runs whether there was an exception or not.
try {
//do something
} catch (Exception e) {}
//do something only if nothing was thrown
Here are two ways:
try {
somethingThatMayThrowAnException();
somethingElseAfterwards();
} catch (...) {
...
}
Or if you want your second block of code to be outside the try block:
boolean success = false;
try {
somethingThatMayThrowAnException();
success = true;
} catch (...) {
...
}
if (success) {
somethingElseAfterwards();
}
You could also put the if statement in a finally block, but there is not enough information in your question to tell if that would be preferable or not.
try {
doSomething();
doSomething2();
} catch (Exception e) {
doSomething3();
}
In this example, doSomething2() will only be executed if no exception is thrown by doSomething().
If an exception is thrown by doSomething(), doSomething2(); will be skipped and execution will jump to doSomething3();
Also note, doSomething3() will be executed if there is an exception thrown by doSomething2();
If no exception is thrown, doSomething3(); will not be executed.
Just put the code in the try block. If an exception is thrown, it will skip to the catch block. If no exception is thrown, the code will just run.
try {
someMethodThatMayThrowException();
codeThatShouldBeRunIfNoExceptionThrown();
} catch (Exception e) {...}
An enhancement to the proposed
try {
somethingThatMayThrowAnException();
somethingElseAfterwards();
} catch (...) {
...
}
from the accepted answer. What you should do is:
void foo() {
try {
doStuff();
} catch (...) {
handleException();
}
}
The above feels like overkill to someone who hasn't been exposed to "clean code thinking".
But the point here: you do not want to mix different abstractions within one method. In other words: you don't have one try block, and more code following behind that within the same method.
You make sure that each and any method contains a straight forward path - you avoid anything that complicates your reading flow. As soon as you get used to writing and reading such kind of code you will find that it takes you dramatically less time to understand your code.
Exceptions for flow control is kind of a bad practice. If you insist, use a boolean variable.
boolean thrown = false;
try {
//do something
} catch (Exception e) {
thrown = true;
}
//do something only if nothing was thrown
if (!thrown) {
// do stuff
}
I was trying to solve this exact problem when I came across this question, and the answers here helped me think it through and realize, at least in my particular case, this was the wrong question I should have been asking.
I wanted to create this method because I was already doing it in main() and wanted to do it elsewhere for portability. So I copied a block of code that contained a try/catch block. However, it turns out, I don't want to copy the catch block at all, because if the creation of the Connection failed, I just wanted to fail completely.
It seems obvious now, but I never wanted to actually catch the exception in the first place. That code was only there because I copy and pasted it. So if you find yourself asking this question because you're in a try block and you might not generate a value, then consider if you just wanted to fail completely and not return anything that way this extra code is unnecessary.
We need to have two functions. They do the same thing but one handles the exceptions and one throws the exception. Note: If to handle exception, the exception has to be handled in the commonFunc() below. It would not work to handle the exception in functionHandlesEx() because to handle the function it needs the variable only available in commonFunc(). In order to re-use code, we got the following. Do you see any problem with it (I can see one problem is: the function throws exception but actually no exception is thrown when isExceptionHandled is true----but Java allows this)? Any better way to do this? We are in Java 6. Thanks.
public void functionThrowsEx() throws Exception e
{
commonFunc(false); //false means does not handle exception
}
public void functionHandlesEx()
{
try
{
commonFunc(true); //true means handle exception
}
catch (Exception e)
{
// do nothing as exception handled
}
}
private void commonFunc(final boolean isExceptionHandled) throws Exception
{
try
{
....
}
catch (Exception e)
{
if (isExceptionHandled)
{
//handle the exception
}
else
{
throw e;
}
}
}
This seems like an overly complicated approach to handling the exception. I understand its toy code to show what you are doing, but I haven't encountered many reasons to create nested calls in order to handle exceptions.
Ideally, the code that can cause the exception should have the means to handle the exception in it, using try...catch, and maybe finally. This logical flow looks like it would be pretty complex in a non-trivial application, and would lead to increased complexity and difficulty in debugging.
You should get rid of the two functions, and avoid nesting try/catch blocks. If you must nest them, make it has straigtfoward as possible by keeping the logic in the same method.
From the code, I'm guessing you want to handle the exception differently based on the state of the program. This code is too complex, and will be difficult to understand for a non trivial app. A better way would be to keep functionHandlesEx and put the exception recovery logic in the handler function.
public void functionHandlesEx() {
try {
//logic here;
}
}
catch (Exception e) {
if(iWantToHandleException) {
//handle exception
}
//do nothing otherwise. Use the finally block for anything else they have in common.
}
}
This is much simpler to understand, and it shouldn't be too hard to refactor it into this form.
I am currently working on the maintenance of a piece of code that is a little bit "Exception Happy." Basically, ever method or anything throws Exception. I'm going to work to take care of that, but, in the meantime, I am wondering what is the best way to handle individual exceptions within a smaller block of code, such as a method. Is it better to do something like this:
public void aMethod()
try {
//Lots of code in here. Many lines.
} catch(Exception e) {
// TODO - Handle All Exceptions, but fairly generically
}
}
Or something like this:
public void bMethod() {
try {
// One line of code.
} catch(Exception e) {
// TODO - Handle a specific Exception (may even involve rethrowing it with more information)
}
// More code.
try {
// Another line of code.
} catch(Exception e) {
// TODO - Handle another specific exception.
}
}
I realize this is a pretty basic question, but after looking at hundreds of methods with Exceptions coming out of every one, I'm starting to wonder how best to handle all of them and what a best practice may be here.
First off, you should only put code in try/catch blocks that is exception worthy. For instance, having an unexpected value is not necessarily an exception, but trying to read from a file that doesn't exist is.
To answer your main question, you should put the exceptionable code in the same try {} block and catch specific questions in order of granularity in multiple catch blocks after the main try.
//Regular code that doesn't need to be covered by a try/catch block
try {
//critical code only
} catch (NullPointerException npe) {
//Code
} catch (RandomException re) {
//code
} catch (Exception e) {
//code
}
The answer to your question is: it depends.
if the code in the try block is coherent where it makes no sense to proceed in the event of an error, the first approach is best
if the code is taking seperate steps that are relatively unrelated (parsing numbers for instance) and can be recovered without aborting the rest of the method the seconds appraoch makes sense
A general remark on the code you inherited; it sounds like exceptions are abused to pass state around, I would refactor so that exceptions are caught at the spot where they can be handled and introduce return values or attributes to handle the state.
your bMethod isn't very useful illustration. Try to reprase it. Anyway, you have two options:
catch exceptions and log them.
catch exceptions and throw new RuntimeException(ex) (rethrow a runtime exception, setting the original as a cause)
Also, you will need to differentiate between exceptions. If your system has many custom exceptions, they are probably defined for a reason, and specific behaviour is expected when one of them is thrown.
If the try/catch block isn't adding useful information, just allow the method to throw the exception and have it handled where the caller can sensibly do something with the exception. This could cut down the number of try/catch significantly (by an order of magnitude).
BTW a trick for rethrowing any exception is.
try {
// do something
} catch (Throwable t) {
Thread.currentThread().stop(t); // rethrow any exception.
}
In addition to the suggestions already made you may also want to consider extracting try/catch blocks from the "meat" of the function.
public void delete(Page page) {
try {
deletePageAndAllReferences(page);
}
catch (Exception e) {
logError(e);
}
}
private void deletePageAndAllReferences(Page page) throws Exception {
deletePage(page);
registry.deleteReference(page.name);
configKeys.deleteKey(page.name.makeKey());
}
private void logError(Exception e) {
logger.log(e.getMessage());
}
This lets you focus your attention on the function you are really interested in without the exception handling getting in your way.