Tuesday, June 29, 2021

When to throw and Catch Exception in Java?

Exceptions are one of the confusing and misunderstood topics in Java, but at the same time, too big to ignore. In fact, good knowledge of Errors and Exception handling practices is one criterion, which differentiates a good Java developer from an average one. So what is confusing about Exception in Java? Well, many things like When to throw Exception or When to catch Exception, When to use checked exception or unchecked exception, should we catch errors like java.lang.OutOfMemoryError? Shall I use an error code instead of an Exception and a lot more? Well, I cannot answer all these questions in one post, so I will pick the first one when to catch or throw any Exception in Java.

This is by far the most genuine question and most basic as well. Lots of Java beginners ask this question, but I don't know how many of them got a satisfactory answer or were able to compare two ways of handling exceptions in Java. 

Yes, In Java there are two ways to handle Exception, catch it or throw it.

In this article, we will look at some scenarios, which guide you through. We will also explore the pros and cons of each approach to make an informed decision. By the way, just remember, I did cover my thoughts about checked vs unchecked exception, so you can refer them here.


When to Catch and throw Exception in Java?

I prefer point-based discussions, as they are easy to understand and reason about, So I will divide my thoughts into different points. You are free to make your own conclusion based upon your own experience and what you read here.

1.  Purpose of Code

The first thing which comes to my mind is what type of Java code you are writing? Are you writing library code, like Apache Commons, Google Guava, or some internal library, which will be used by many developers? or you are writing a real-world application like a Core Java application to process orders for electronic trading or an algorithmic trading platform or an eCommerce web application.

Why catching and throwing exception depends upon the type of application? because one of the requirements for these kinds of critical business applications is not to crash during business hours. If you don't catch a checked Exception or RuntimeException, your application will crash if an exception occurs. This is a big no-no for critical services.

It's not reasonable for an electronic order processing engine to crash just because of an incorrect order, reasonable thing is to drop that order and move forward to another order. This can only be done if you catch RuntimeException thrown by your order processing logic, inside your order processing loop.

Now let's come back to library code, When you are writing library code likewriting a method to divide two integer numbers, one precondition is that denominator should not be zero.

If client code passes you zero then you are well within your right to throw an Exception because you said it before and it's the client's fault. Catching an arithmetic exception would be straight wrong in this case. Now the client is an application, should it catch this exception or not? As I said it should catch if it’s coming from the input it is processing, to log the error and move to the next input.

2.  Performance

The second thing, which comes to my mind is performance. Exceptions are not cheap, when you throw an Exception, it creates a new Throwable object and copies full stack trace, this is an expensive operation. 

So throwing Exception from loops is a big no-no. Depending upon the situation and requirement, sometimes returning a boolean is enough.

 If you know that a method is used in the critical path, or called frequently like its part of that 10% code that executes 90% of the time, then don't throw Exception from that code. It would be made your application slow because of the cost of creating an Exception and throwing it.

3.  Return type of Method

The third point, which may help you to decide between catching or throwing an Exception is, the type of result a method can return. A good example is the equals() method, which returns false if compared to a null object, instead of throwing NullPointerException

This makes sense because all you are interested in the known is whether two objects are equal or not. But comes to comapreTo(), where you want to know if two objects are greater than, less than, or equal to each other. If you pass null, it cannot decide and return any of these results, so it throws NullPointerException.

4.  Recovery possibility

Catch Exceptions if you can recover from errors otherwise throw them to someone, who can handle them. Yeah, it sometimes looks as simple as that. In the real world, there are hardly any scenarios, where developers can take recovery action, it also depends upon the business requirements and judgment of the developer. For example, one case where I have seen good use of catching exceptions is, retry mechanism.

For example, if your code must need database connectivity to process an order and you suddenly lost the database connection then you should not abort the order, instead, you should keep retry to connect the database.

Generate alert that system cannot function, because the database is not available, hold incoming orders into blocking queue. Stop accepting orders once your memory threshold reaches. In business-critical applications essential services like database, Middleware(MQ or Tibco) are usually restored quickly, either by failover or by routing to another instance. 

Catching java.net.ConnectException: Connection refused is common practice FIX-based development, where FIX Engines keeps retrying with some time interval until the counterparty's FIX server starts accepting the connection.

When to throw and Catch Exception in Java?



5. Cost

Catch Exception if the cost of catching is less than filtering. Sometimes we write filtering code to filer messages which our code cannot process like processing unknown types of FIX messages. When you write a filtering code, it checks every message for supported message types, which may cost some CPU cycles. 

Now if you come to know that that exceptional scenario happens once in a million orders, then it’s better to catch that exception than wasting the CPU cycle in filtering code.

These were a couple of points, which I take into consideration before throwing or catching an Exception in Java. It is also advised not to catch Errors like java.lang.OutOfMemoryError, because you can't do anything even after catching that error.

Let your application fail fast in case of System error e.g. if it’s not able to find any native library by throwing java.lang.Unsatisfied link error. Catch exception if you can recover either by retrying or taking an alternative step.

For example, a router code can catch exceptions for some time, before forwarding that request to another instance. I will add a few more tips when I will be able to recall or come across any useful tips. By the way, feel free to add ways of catching or throwing exceptions in Java.

That's all about when to throw and catch Exception in Java. As I said, exception handling is important but deciding when to throw or catch exceptions is really tricky. By following these guidelines and using your judgment, you can decide when it makes sense to throw an exception and when to catch them. If you have any other ideas which can help Java developer make this important decision feel free to share. I would love to hear how are you handling exceptions in Java. 

No comments:

Post a Comment

Feel free to comment, ask questions if you have any doubt.