{"id":83,"date":"2021-01-17T23:11:00","date_gmt":"2021-01-17T21:11:00","guid":{"rendered":"http:\/\/victorrentea.ro\/blog\/?p=83"},"modified":"2021-01-29T01:18:58","modified_gmt":"2021-01-28T23:18:58","slug":"exception-handling-guide-in-java","status":"publish","type":"post","link":"https:\/\/victorrentea.ro\/blog\/exception-handling-guide-in-java\/","title":{"rendered":"Exception Handling Guide in Java"},"content":{"rendered":"<div id=\"bsf_rt_marker\"><\/div>\n<p>This article presents a pragmatic, clean approach to working with exceptions in the Java applications we build today.<\/p>\n\n\n\n<p>If you want a live walk through the concepts in this article and the others related to exception handling, here is a talk I gave on this topic at the Java Champions Conference in 2021:<\/p>\n\n\n\n<p><a href=\"https:\/\/www.youtube.com\/watch?v=LRwCE7GreSM\">https:\/\/www.youtube.com\/watch?v=LRwCE7GreSM<\/a><\/p>\n\n\n<h2>A Bit of History<\/h2>\n<p>At first, there were no exceptions.<\/p>\n<p>Forty years ago, when a C function wanted to signal an abnormal termination, it would return a <code>-1<\/code> or <code>NULL<\/code>. But if the caller forgot to check the returned value, the error would go unnoticed.<\/p>\n<p>In 1985, C++ tried to fix that by introducing exceptions that propagate down the call stack and, unless caught, terminate the program execution. However, developers suddenly were facing a new challenge: how would the caller know what exceptions are thrown by the function they called?<\/p>\n<p>Ten years later, Java was born. Since all developers back then were using C\/C++, one goal of Java was to attract them with features like Garbage Collection, safe references (instead of pointers), smooth build process, unified source code (instead of .h\/.cpp), portability, and others. At the same time, Gosling, the father of Java, tried to fix the problem of mysterious exceptions by forcing developers to become aware of <strong>checked exceptions<\/strong> thrown by the functions they called. Of course, some errors couldn\u2019t be foreseen (like <code>ArrayOutOfBoundsException<\/code> or <code>NullPointerException<\/code>), so these remained invisible <strong>runtime exceptions<\/strong>.<\/p>\n<p>You probably already know that checked exceptions should be used only for &#8220;recoverable errors&#8221;. Only then it pays to force your caller to <code>try-catch<\/code> or <code>throws<\/code> your exception.<\/p>\n<p>But all this was happening in <em>The Age of Libraries<\/em>. In the \u201890s, developers realized the importance of reuse: libraries and frameworks were being created everywhere. The truth is that when writing a library, it\u2019s very tempting to consider that the code using it might be able to recover from a wide range of errors, especially if you don\u2019t have a very clear picture of how your clients will use it. Thus, the urge towards checked exceptions: let\u2019s notify our callers of everything,&#8230; as they might be able to recover.<\/p>\n<p>Furthermore, back in those days, many applications implemented UI or batches, and these typically need to handle the exceptions to prevent them from terminating the program.<\/p>\n<p>But that age is gone.<\/p>\n<p>In the applications we write today, we rarely recover from exceptions. Instead, we terminate the execution of the current use-case ASAP. In a web application, we would return a 400\/500 HTTP status code. When handling messages from queues, we might reject that message. And in a batch, we would probably skip or report that line with (eg) Spring Batch\u2019s assistance. We rarely recover from an error anymore.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/victorrentea.ro\/blog\/wp-content\/uploads\/2020\/12\/image-1608420669024.png\" alt=\"file\" \/><\/p>\n<p><strong>Disclaimer<\/strong>: This article is about building custom applications, like almost all of my client companies are doing. It is only partially applicable to writing framework\/library code.<\/p>\n<p>Sadly, 25 years later, checked exceptions are still here.<\/p>\n<h2>Only use Runtime Exceptions<\/h2>\n<p>Imagine the following (overly?)simplified configuration loader:<\/p>\n<pre><code>class Config {\n   public static Date getLastPromoDate() throws ParseException, IOException {\n     Properties props = new Properties();\n     try (Reader reader = new FileReader(\"config.properties\")) {\n        props.load(reader);\n     }\n     SimpleDateFormat format = new SimpleDateFormat(\"yyyy-MM-dd\");\n     return format.parse(props.getProperty(\"last.promo.date\"));\n   }\n}<\/code><\/pre>\n<p>(<strong>Disclaimer<\/strong>: config files shouldn\u2019t be read repeatedly but cached somehow; this is just a simplified example to illustrate some standard exceptions occurring.)<\/p>\n<p>And here is the business logic code using our <code>Config<\/code> class:<\/p>\n<pre><code class=\"language-java\">public void applyDiscount(Order order, Customer customer) {\n try {\n   if (order.getOfferDate().before(Config.getLastPromoDate())) {\n      System.out.println(\"APPLYING DISCOUNT\");\n      order.setPrice(order.getPrice() * (100 - 2 * customer.getMemberCard().getFidelityDiscount()) \/ 100);\n   } else {\n      System.out.println(\"NO DISCOUNT\");\n   }\n } catch (Exception e) {\n   \/\/ TODO\n }\n}<\/code><\/pre>\n<h3>The Diaper Pattern<\/h3>\n<p>Have you ever encountered an empty <code>catch<\/code> block? One in every 10 developers attending my training sessions found this in production code at some point in their career. This terrible mistake even got a name:<\/p>\n<blockquote>\n<p>The <strong>Diaper Anti-Pattern<\/strong> = catching all exceptions and just silencing them.<\/p>\n<\/blockquote>\n<p>I would name it <strong>&#8220;shawarma-style error handling&#8221;<\/strong> when explaining it to younger developers for two reasons. First, you don&#8217;t know precisely what exception you swallow. Secondly, shawarma-maker becomes a possible future career path if you regularly apply this technique (I\u2019m evil here, right?).<\/p>\n<p>But let me explain why.<\/p>\n<p>In production, when the <code>applyDiscount()<\/code> method above got called, it abruptly terminated for some orders without printing neither <code>APPLYING DISCOUNT<\/code>, nor <code>NO DISCOUNT<\/code>. Can you figure out what happened for those orders?<\/p>\n<p>Yup&#8230; a NullPointerException occurred in the <code>if<\/code> condition for the Orders having a <code>null<\/code> offer date, but then the exception was hidden by the Diaper Pattern. You can experience it yourself by running the <code>InProduction<\/code> class from <a href=\"https:\/\/github.com\/victorrentea\/exceptions-guide\/commit\/2f9b92a2e1ae9ab35bc08cadf9cd10b5e12c46ff\">this commit<\/a>. By the way, I wrote another <a href=\"avoiding-null-pointer-exception\">blog post<\/a> about how to avoid <code>NullPointerException<\/code>, using <code>Optional<\/code> and a self-validating data model.<\/p>\n<p>But the real-world code is never this simple, and you can waste hours to find such a swallowed exception in typical production code. You will probably have to breakpoint around, as there&#8217;s nothing in the logs. This is bad, very, very bad.<\/p>\n<p>But how did the code end up like that?<\/p>\n<p>First of all, you can selectively catch multiple exceptions using the syntax <code>catch (ParseException | IOException)<\/code> only since Java 7, released in 2011. For a large successful Java application, ten years is not so long ago, so the author of the code might have caught <code>Exception<\/code> because he didn&#8217;t want to repeat an identical <code>catch<\/code> block (one for <code>ParseException<\/code> and one for <code>IOException<\/code>).<\/p>\n<p>Okay, but still, why is the <code>catch<\/code> block empty ?!?<\/p>\n<p>Eh&#8230; that&#8217;s another story. Three years ago, they might have sent an email to ask how to handle that exception, or they might have just rushed and forgotten to handle it. Or perhaps one of the exceptions they caught there was regularly popping, polluting the log every minute.<\/p>\n<p>In the case of repeating exceptions, I would log that exception on the <code>TRACE<\/code> level, as you can decrease the log level in production without a restart if needed, via <a href=\"https:\/\/www.baeldung.com\/spring-boot-changing-log-level-at-runtime\">Spring Actuator<\/a> or via a <a href=\"http:\/\/logback.qos.ch\/manual\/jmxConfig.html\">Logback JMX Bean<\/a>. But before doing that, I would first try to prevent that exception from occurring by doing some pre-checks. If that\u2019s not possible, I will make sure I catch and <code>log.trace<\/code> that exception exactly around the line throwing it. Be very cautious with ignoring exceptions or logging them at a low log level!<\/p>\n<p>You would never swallow exceptions, I know.<\/p>\n<p>As a matter of fact, even the catch block auto-generated by Eclipse or IntelliJ would <code>.printStackTrace()<\/code> by default, so you\u2019re safe, right?<\/p>\n<p>By the way, here\u2019s a fun fact for you: <code>.printStackTrace()<\/code> prints the exception to <code>System.err<\/code>, not <code>System.out<\/code>, and by default, most frameworks (Spring Boot included) don&#8217;t capture <code>System.err<\/code> to the log file unless you <a href=\"https:\/\/stackoverflow.com\/questions\/11187461\/redirect-system-out-and-system-err-to-slf4j\">take explicit steps<\/a>. So despite <code>e.printStackTrace()<\/code>, you will probably <strong>won&#8217;t see anything in your log<\/strong> file. Oops!<\/p>\n<p>But let\u2019s come back to our beloved <code>NullPointerException<\/code>. By the way, do you know that songs were written for this exception? (and other hard to trace exceptions in general)<\/p>\n<p><iframe loading=\"lazy\" title=\"Ode to Null Pointer Exception\" width=\"770\" height=\"433\" src=\"https:\/\/www.youtube.com\/embed\/q0jUr2gCfmk?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen><\/iframe><\/p>\n<p>But here it is, the exception:<\/p>\n<pre><code>   C:\\workspace\\openjdk-15_windows-x64_bin\\jdk-15\\bin\\java.exe ... victor.training.exceptions.InProduction\n   java.lang.NullPointerException: Cannot invoke \"java.util.Date.before(java.util.Date)\" because the return value of \"victor.training.exceptions.model.Order.getOfferDate()\" is null\n       at victor.training.exceptions.Biz.applyDiscount(Biz.java:20)\n       at victor.training.exceptions.InProduction.main(InProduction.java:13)<\/code><\/pre>\n<p>Let&#8217;s take some time to enjoy the nice message reported from Java 15 onwards for <code>NullPointerException<\/code>s. You could be an absolute rookie and still get where the problem is. Up to Java 11 LTS however, the NPE had a very opaque message:<\/p>\n<pre><code>   C:\\Users\\victo\\.jdks\\corretto-11.0.7\\bin\\java.exe ... victor.training.exceptions.InProduction\n   java.lang.NullPointerException\n       at victor.training.exceptions.Biz.applyDiscount(Biz.java:20)\n       at victor.training.exceptions.InProduction.main(InProduction.java:13)<\/code><\/pre>\n<p>Smooth!<\/p>\n<p>So, how should we handle those nasty checked exceptions?<\/p>\n<p>By rethrowing them wrapped in a <code>new RuntimeException(checkedException)<\/code>, of course.<\/p>\n<blockquote>\n<p>Never <strong>decapitate<\/strong> your exceptions: always set the <strong>cause<\/strong> of the rethrown exception to the original exception, whenever there is one.<\/p>\n<\/blockquote>\n<p><img decoding=\"async\" src=\"https:\/\/victorrentea.ro\/blog\/wp-content\/uploads\/2020\/12\/image-1608418179133.png\" alt=\"file\" \/><\/p>\n<p>But where should we convert checked exceptions into runtime ones? Inside <code>Config.getLastPromoDate()<\/code> or within <code>Biz.applyDiscount()<\/code>? To understand the right answer, let\u2019s talk a bit about abstractions.<\/p>\n<h3>Checked Exceptions are an Abstraction Leak<\/h3>\n<p>An abstraction is a simplification of reality, attempting to hide the (complex) implementation details. From a design perspective, a method like <code>getLastPromoDate() throws IOException<\/code>, is an <strong>abstraction leak<\/strong> because it reveals the implementation detail that it\u2019s working with files. Why should the caller know, or care, that there are files or any other sort of I\/O involved?<\/p>\n<p>From the same perspective, you should avoid adding implementation details to your method signatures. You should generally avoid returning Files, ResultSet, or foreign data structures or taking them as parameters. Of course, there are exceptions to this rule, but I will dive more in-depth on this in a later blog post about the Adapter and Dependency Inversion Principle.<\/p>\n<p>In our case <code>getLastPromoDate()<\/code> , that&#8217;s why we should NOT declare any checked exceptions but instead wrap the checked exceptions in a <code>RuntimeException<\/code> and throw that instead, to hide the <strong>implementation detail<\/strong> that it&#8217;s using files and parsing dates. Here&#8217;s the new code (<a href=\"https:\/\/github.com\/victorrentea\/exceptions-guide\/commit\/99288a3fd8b34e64323855f05d6377dea495c1b8\">commit<\/a>):<\/p>\n<pre><code>   public static Date getLastPromoDate() {\n     try{\n        Properties props = new Properties();\n        try (FileReader reader = new FileReader(\"config.properties\")) {\n           props.load(reader);\n        }\n        SimpleDateFormat format = new SimpleDateFormat(\"yyyy-MM-dd\");\n        return format.parse(props.getProperty(\"last.promo.date\"));\n     } catch (ParseException | IOException e) {\n        throw new RuntimeException(e);\n     }\n   }<\/code><\/pre>\n<h3>How to handle Checked Exceptions?<\/h3>\n<p>There are two main reasons why we only allow runtime exceptions through our central code today:<\/p>\n<ol>\n<li>Avoid abstraction leak and<\/li>\n<li>Reduce the change of Diaper Anti-Pattern, since developers don\u2019t have to <code>try\/catch\/throws<\/code> exceptions<\/li>\n<\/ol>\n<p>We should catch any checked exception attempting to enter our core logic and rethrow it wrapped in a runtime exception. We should then handle this new exception at the end of the workflow, far away, in a top-level global exception handler.<\/p>\n<blockquote>\n<p><strong>Best Practice<\/strong>: Do not propagate checked exceptions through your core logic.<\/p>\n<\/blockquote>\n<p>Many years after this became the widely accepted best practice, many developers were still suffering from <a href=\"https:\/\/en.wikipedia.org\/wiki\/Post-traumatic_stress_disorder\">Post-Traumatic Stress<\/a> after having spent too many nights hunting for swallowed exceptions. Those people developed another bad habit, on the other extreme:<\/p>\n<pre><code>} catch (ParseException | IOException e) {\n    log.error(e.getMessage(), e);\n    throw new RuntimeException(e);\n}<\/code><\/pre>\n<blockquote>\n<p><strong>The Log-Rethrow Anti-Pattern<\/strong>: \u201cI\u2019ll rethrow it, okay, but let me just log it here anyway, just in case\u201d said the elder.<\/p>\n<\/blockquote>\n<p>Why is this a bad practice? Because printing and throwing back the exception will log the error multiple times, turning your log into a frustrating, unreadable pile of garbage. Try it yourself: <a href=\"https:\/\/github.com\/victorrentea\/exceptions-guide\/commit\/dd66304cdd7e808e7e277efb2e02876e2735819f\">commit<\/a>. All this because the developers are afraid that the exception might slip out without being logged anywhere.<\/p>\n<p>The real solution is to have a global exception handler put in place at every exit point that safely logs any unhandled exception. You can read more about how to implement such a global exception handler for REST endpoints in <a href=\"presenting-exceptions-to-users\">my previous blog post on this topic<\/a>.<\/p>\n<blockquote>\n<p><strong>Best Practice<\/strong>: make sure any unhandled exceptions are logged, <strong>in whatever thread<\/strong> they might occur.<\/p>\n<\/blockquote>\n<p>The &#8216;thread&#8217; part above is the challenge because, besides HTTP endpoints, our code might run on other threads like thread pool executors, <code>CompletableFuture<\/code>, @Async, @Scheduled, message endpoints, or others. Take careful measures to log exceptions on whatever thread they occur.<\/p>\n<blockquote>\n<p>Your developers should feel safe that exceptions are never lost.<\/p>\n<\/blockquote>\n<p>There is almost no reason left to add a <code>catch<\/code> within your core domain logic if you do this. Unless you&#8217;re retrying or working around an error condition, but you almost never do that.<\/p>\n<h2>Reasons to Catch-Rethrow<\/h2>\n<p>There are four reasons to catch an exception and rethrow it wrapped in a new one:<\/p>\n<ol>\n<li>Report a particular user-friendly message<\/li>\n<li>Unit-Test a thrown exception<\/li>\n<li>Report debugging information via new exception message<\/li>\n<li>Get rid of a Checked Exception, when none of the above applies<\/li>\n<\/ol>\n<p>We covered the first two points in <a href=\"presenting-exceptions-to-users\">this article<\/a>, emphasizing the benefit of relying on enum error codes to distinguish between interesting error conditions.<\/p>\n<p>For (4) you can consider using <code>@SneakyThrows<\/code> from Lombok, as explained in <a href=\"hide-checked-exceptions-with-sneakythrows\">this article<\/a>, or <code>Unchecked<\/code> from jOOL in case you want to <a href=\"exceptions-and-streams\">handle checked exceptions when working with Streams<\/a>.<\/p>\n<p>This leaves us to focus on (3) in the following.<\/p>\n<p>Have you ever had to use breakpoints to debug an occurring exception? If you did, then here&#8217;s a trick you can use to avoid doing that: the <strong>Catch-Rethrow-with-debug-message<\/strong> pattern. You catch the exception in a method having some interesting details that you\u2019d like to inspect when debugging it, and rethrow the exception wrapped in a new exception with a message that captures those details:<\/p>\n<pre><code>    long interestingId;\n    ...\n} catch (RuntimeException e) {\n    throw new RuntimeException(\"Failed for \" + interestingId, e);\n}<\/code><\/pre>\n<p>When the exception stack trace unfolds at the end, you&#8217;ll see the <code>interestingId<\/code> nicely laying in the log file, enabling a cold, relaxed analysis.<\/p>\n<blockquote>\n<p>Use exception messages to convey debugging information for developers.<\/p>\n<\/blockquote>\n<h2>Conclusions<\/h2>\n<ul>\n<li>Avoid Diaper Anti-Pattern: don\u2019t ever swallow exceptions<\/li>\n<li>If you have to catch exceptions, catch them as close as possible to their origin<\/li>\n<li>Only allow Runtime Exceptions to pass through the core logic of your application<\/li>\n<li>Consider <code>@SneakyThrows<\/code> and <code>Unchecked<\/code> to get rid of checked exceptions<\/li>\n<li>Avoid Log-Rethrow Anti-Pattern: set up and trust the global exception handler<\/li>\n<li>Use exception message to convey debugging information todevelopers<\/li>\n<\/ul>\n<h3>More Tips<\/h3>\n<ul>\n<li>Don\u2019t throw from a <code>finally<\/code> block: the new exception might hide a preexisting exception<\/li>\n<li>Throw <em>before<\/em> mutating an object state: leave the objects\u2019 state unaltered<\/li>\n<li>Don\u2019t use exceptions for <em>normal<\/em> flow control: they are expensive, and they can smell like a <code>GOTO<\/code> instruction<\/li>\n<\/ul>\n<h3>Further Reading<\/h3>\n<ul>\n<li>How to <a href=\"avoiding-null-pointer-exception\">Avoid NullPointerException with Optional<\/a><\/li>\n<li>How to handle <a href=\"exceptions-and-streams\">Exceptions occurring in Streams<\/a><\/li>\n<li>How to <a href=\"hide-checked-exceptions-with-sneakythrows\">sneaky throw checked exceptions with Lombok<\/a><\/li>\n<li>How to present exceptions to users and set up a global exception handler for your REST endpoints &#8211; <a href=\"presenting-exceptions-to-users\">my blog post<\/a>.<\/li>\n<li>How to handle Async exceptions: exceptions occurring in other threads (Executors, <code>@Async<\/code>, CompletableFuture, Reactive-X, Message Handlers&#8230;)<\/li>\n<li>How to handle <code>InterruptedExceptions<\/code>: nice <a href=\"https:\/\/dzone.com\/articles\/how-to-handle-the-interruptedexception\">dzone article<\/a><\/li>\n<\/ul>\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>This article presents a pragmatic, clean approach to working with exceptions in the Java applications we build today.<\/p>\n","protected":false},"author":1,"featured_media":210,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[8,6,7],"class_list":["post-83","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-practical-tips","tag-best-practices","tag-exceptions","tag-java"],"_links":{"self":[{"href":"https:\/\/victorrentea.ro\/blog\/wp-json\/wp\/v2\/posts\/83","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/victorrentea.ro\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/victorrentea.ro\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/victorrentea.ro\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/victorrentea.ro\/blog\/wp-json\/wp\/v2\/comments?post=83"}],"version-history":[{"count":19,"href":"https:\/\/victorrentea.ro\/blog\/wp-json\/wp\/v2\/posts\/83\/revisions"}],"predecessor-version":[{"id":225,"href":"https:\/\/victorrentea.ro\/blog\/wp-json\/wp\/v2\/posts\/83\/revisions\/225"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/victorrentea.ro\/blog\/wp-json\/wp\/v2\/media\/210"}],"wp:attachment":[{"href":"https:\/\/victorrentea.ro\/blog\/wp-json\/wp\/v2\/media?parent=83"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/victorrentea.ro\/blog\/wp-json\/wp\/v2\/categories?post=83"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/victorrentea.ro\/blog\/wp-json\/wp\/v2\/tags?post=83"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}