Java Exception Handling Strategy

I am working on an application in which a process continues, like this UI β†’ backend process β†’ interface result in a user interface.

In my code, I handled my exceptions using try, catch. But in the code I have so many repeated exceptions that can throw the same exceptions in different classes.

So, I plan to make an exception handling strategy so that when an exception is thrown, it will be redirected to a separate exception handling code (something like a separate class of an exception handling library). so it should not be inside my business logic.

Can someone suggest me how to implement it and would it be a better idea to deal with my exceptions? or Can someone suggest me an exception handling method to do this other than mine?

Thanks, awaiting your reply.

+3
source share
2 answers

If you make exceptions that are too low-level, catch them a few calls above and pack them as a more general and meaningful exception with a user-friendly message that went wrong and drop them again to the highest possible level where you stop your application and view them in any way (for example, on the label) for the user.

from Effective Java ( item 61 ) :

This is confusing when a method throws an exception that does not have a visible connection to the task being performed. This often happens when a method throws an exception thrown by a lower level of abstraction. This not only discourages, but also pollutes the higher-level API with implementation details. If the implementation of a higher level change in a subsequent release, the exceptions that it throws also change, potentially violating the existing client of the program.

To avoid this problem, higher levels should catch exceptions at the lower level and instead raise exceptions that can be explained in terms of higher level abstractions. This idiom is known as exception translation:

// Exception Translation try { // Use lower-level abstraction to do our bidding ... } catch(LowerLevelException e) { throw new HigherLevelException(...); } 

Although the translation of exceptions is superior to the pointless distribution of exceptions from the lower layers, it should not be abused. where possible, the best way to handle exceptions from the lower layers is to avoid them, ensuring that lower-level methods are successful. Sometimes you can do this by checking the correctness of the methods of a higher level of parameters before passing them to lower levels.

If it is not possible to exclude exceptions from the lower layers, the next best thing is for the higher level to silently work around these exceptions, isolating the higher level caller from the lower level problem. Under these conditions, it could be to log an exception using some suitable logging tool such as java.util.logging. This allows the administrator to investigate problems by isolating the client code and the end user from it.

In general, if it is not possible to prevent or handle exceptions from the lower levels, use exception translation if the lower level method guarantees that all its exceptions are suitable to a higher level. The chain provides the best of both worlds: this allows the corresponding exception to be thrown at a higher level, while fixing the root cause of the failure analysis (paragraph 63).

+6
source

From Effective Java (Joshua Bloch)

  • Use exceptions exclusively for exceptional conditions (never use for normal control flow)
  • Use checked exceptions for recoverable conditions and runtime exceptions for programming errors.
  • Avoid unnecessary use of checked exceptions

Avoid marked exceptions.

http://www.mindview.net/Etc/Discussions/CheckedExceptions http://www.ibm.com/developerworks/java/library/j-jtp05254/index.html

  • Checked exceptions are often considered erroneous. This is not a bad idea, but people really don’t understand how to use them.
  • Java frameworks such as Spring, Hibernate ... they all basically throw unchecked exceptions.
  • C # did not implement checked exceptions as intended. Scala.
  • This is not because he did not check that you cannot catch him.
  • This is not because he did not check that you cannot translate it (wrap).
  • This is not because he did not verify that he was not part of the contract. In fact, you can declare a method to throw excluded exceptions.
  • Checked exceptions increase communication between the client and the library.

It is very important to understand that any part of the code may throw an exception. The fact is that this is not because the method declares an IOException, that it cannot throw any other exception. It can throw any other runtime exception (general or custom). With checked exceptions, developers tend to think otherwise and believe that catching an IOException will handle all exceptional cases, but this is not true!


Compile-time function only

Only the compiler will tell you when you forgot to catch or throw the checked exception. There is no difference at runtime.

This means that by using type-erase tricks, you can throw a checked exception without even requiring it to be part of the method contract.

You can find examples of this trick called SneakyTrow here: fooobar.com/questions/284396 / ...

Lombok also provides the @SneakyThrow annotation for applying methods, so you don't need to declare checked exceptions in the method signature.


Use only checked exceptions when the client of your class may recover from the exception.

This is a recommendation from Sun.

Basically, trying to connect to the database will throw a checked exception, and the retry strategy code will catch these checked exceptions when attemps connects. When the number of retries is exceeded, the retry strategy will throw an exception that throws an exception, which means that it is not an exception for recovery, because the recovery strategy has already been tried. You can use Spring RetryTemplate for this, by the way.


Avoid Exception Codes

The type of exception should be sufficient to make flow control decisions. Exception parsing or flow control will produce useless code. Add more exception types as many exception codes you have.


Crash fast

Let all unrecoverable exceptions be thrown to the IHM level. If you use a framework that declares checked exceptions, and you don't have a recovery strategy for them, feel free to wrap them in unchecked exceptions.

If you cannot recover, you should not do catch and write. Or, even worse, you should not do "catch and return null". This will lead to inconsistent software, and you will probably have another exception raised later in your program, but you won’t be able to understand why. A return value of null will later throw a NullPointerException.

IHM-level technology may have an exception handler / mapper. Web IHM layers have exception mapping mechanisms, so you can say that "this exception generates a 404 error."


Functional approach

For information: in functional languages ​​it is often considered improper practice to use exceptions to control flow. Instead of throwing exceptions, we usually return "extended types", for example [Error, MyResultType].

The returned instance is either an error or successful, and an instance of MyResultType is returned.


Exceptions not thrown for flow control

Creating an exception has a cost (creating a stacktrace). It costs a lot more than a regular thread using if, else ... Do not use them to control the flow if you can avoid them.

Basically, you can always avoid them, but in Java it is sometimes more convenient to use them to control flows in some situations. In functional languages, Either the monad helps again.


Use statements

If something from your program is considered a true developer, use assertions to ensure that your assertion is true. Take a look at Guava premises: https://code.google.com/p/guava-libraries/wiki/PreconditionsExplained

Or you can use Java built-in statements or some kind of custom code. This helps to quickly fail.

+5
source

All Articles