During vulnerability scanning, we figured out there were a lot of exceptions handled through the print statement. That’s not a very efficient way of handling exceptions.
Print statements are still better than not writing anything to handle. That’s known as swallowing an exception. A good approach to handle exceptions is to write some way to log those exceptions or throw those exceptions with stack trace during runtime. In this post, I showed some ways of handling exceptions.
What are the exceptions?
Exceptions are error events. These events happen during the runtime of a program. This generally disrupts the flow of the program.
There are three components to exception handlers – try, catch, and finally.
try
– This part of exception handling contains code that will be executed during every flow.
catch
– If code in try part throws a runtime exception, that will be caught in catch part.
finally
– This contains the code you want to execute after trying part of the execution is done. This ensures that finally block is executed even when unexpected exceptions occur. It is mostly used to clean up resources.
Types of Exceptions
- Unchecked Exceptions – Exception types that are direct or indirect subclasses of a class
RuntimeException
, those are the unchecked exceptions. - Checked Exceptions – Exceptions that inherit
Exception
class are known as checked exceptions.RuntimeException
are also extended fromException
, but client code doesn’t have to handle them, while Checked exceptions have to be handled by catch or throws clause.
How to handle Exceptions
What exceptions to use? Checked or Unchecked?
In case the code doesn’t know what to do if an exception is thrown, it should be an unchecked exception. If code using an exception knows what to do to recover from that exception along with logging that information, that should be checked exception.
Preserve encapsulation
Don’t propagate an exception from the data access layer to the business object layer.
Example – SQLException
is a RuntimeException
. If the data access layer throws this exception in the following manner, the catch block will not do anything but will suppress it.
public void dataAccessCode() { try { } catch (SQLException ex) { ex.printStacktrace(); } }
On the other hand, to preserve encapsulation, the same runtime exception can be converted into another unchecked exception like below
public void dataAccessCode() { try { } catch (SQLException ex) { throw new RuntimeException(ex); } }
Best practices for Exceptions
1) Use finally block for cleaning the code
2) Do not ignore or suppress an exception
3) Log exceptions once
4) Do not use exceptions for flow control
References
Pingback: Error Handling and Logging in Spring Boot REST API – Part III | Code Junkie