Warning: Parameter 1 to Language::getMagic() expected to be a reference, value given in /home/wikija5/public_html/w/includes/StubObject.php on line 58

Warning: Parameter 3 to renderSEO() expected to be a reference, value given in /home/wikija5/public_html/w/includes/parser/Parser.php on line 3243
10 best practices with Exceptions - WikiJava
Thursday, 30th October 2014
Follow WikiJava on twitter now. @Wikijava

10 best practices with Exceptions

From WikiJava

Jump to: navigation, search
The author suggests:

buy this book


This article enumerates ten best practices to adopt when you are programming in Java and you are using Exceptions.

An exception is an event that breaks the normal flow of the program. Any event may be an exception, but in Java we normally use exceptions when errors happen. For this reason we normally refer to exceptions as to the error handling system of Java.

This article will assume some basic knowledge about the exceptions and will attempt to provide guidelines on how to best use them. If you find it hard to read this article refer to the tutorial about exceptions from Sun, which gives a good basics on this topic.

Contents

Relevancy

A method can only throw the exceptions that are relevant to its interface.

For example see the constructor:

java.io.FileInputStream.FileInputStream(String name) throws FileNotFoundException

Which opens a file on the disk for reading bytes. It makes sense that this constructor throws a FileNotFoundException. But it would make no sense at all if it would throw an IndexOutOfBoundsException. This exception would not be meaningful in the FileInputStream context.

So keep the exceptions you throw relevant to the interface.

Encapsulation

To follow the principle of relevancy it may be useful the trick of encapsulating exceptions one into another.

For example if your method is throwing an exception received from another method (which is a very common scenario) it should encapsulate it in a locally generated Exception class.

Like it's shown in the example:

try {
  return new FileOutputStream(fileName);
} catch (FileNotFoundException e) {
  throw new ActionException(e);
}

The method receives an Exception generated by the FileOutputStream constructor, and throws it to the next method in the stack trace encapsulating it in a ActionException, so it throws only exceptions that are relevant to the interface.

The method that catches this exception can at any time get the information about the FileNotFoundException, encapsulated in the main exception, by using the getCause() method.

If you print the stack trace you will see a list of caused by: strings, containing all relevant information about all the nested exceptions.

Reason

The exceptions must always say what caused them. There are two viable approaches:

  • To generate a separate exception for each event.
  • To create a generic exception and describe what caused it

The first approach allows you to write different code for handling the different events, but it requires you to write lot of Exception classes and in some case it could be just too much.

The second approach is more concise, but it makes it difficult to handle the different situations.

As it happens very often in programming the best solution is in the middle, where you balance generating separate exceptions and using one exception for other cases.

The rule of the thumb in this case could be to generate a separate Exception class for the exceptions you want to handle specifically with separate code, while use a single generic Exception class for exceptions you want to treat in a default way, for example you just want to bubble them up the stack trace to show an error message.

Exception names

The names of the exceptions should always be meaningful and must express what happened that caused them. For example java.io.FileNotFoundException has a good name and tells you that a file was not found. The class java.lang.Exception provides a generic exception class for all the situations that are not managed by the JDK API. My advice is to avoid using the java.lang.Exception as it is too generic and gives too little information about what went wrong.

My approach is that whenever I feel like throwing java.lang.Exception I instead create a new exception class that subclasses java.lang.Exception. I use this new Exception class to manage the generic errors generated by my class.

For example, if I am writing the Draw class and see that in one of it's methods I need to throw an exception, I can create the DrawException class, extending java.lang.Exception.

DrawException works exactly in the same way as Exception, but when I see it in the stacktrace if the exception occurs, I understand immediately who generated it and when and why. When my program grows a little and I start using the encapsulation principle mentioned before in this article I will end up with a stacktrace with all caused by: followed by names of classes I wrote. This simplifies debugging a lot.

We used this principle in the example mentioned above (repeated here):

try {
  return new FileOutputStream(fileName);
} catch (FileNotFoundException e) {
  throw new ActionException(e);
}


The ActionException class would be as simple as follows:

package org.wikijava.network.batBot.delegates.interfaces;
 
public class ActionException extends Exception {
 
    public ActionException() {
	// TODO Auto-generated constructor stub
    }
 
    public ActionException(String message) {
	super(message);
	// TODO Auto-generated constructor stub
    }
 
    public ActionException(Throwable cause) {
	super(cause);
	// TODO Auto-generated constructor stub
    }
 
    public ActionException(String message, Throwable cause) {
	super(message, cause);
	// TODO Auto-generated constructor stub
    }
 
}

This class was completely automatically generated by Eclipse. Note that It contains only the four constructors. All the other methods are inherited from java.lang.Exception

Balance what you catch

Similarly to the reason principle not only we can decide what to throw, we have control also on what to catch. We can use two approaches for our catch blocks:

  • a single catch block for all. For example:
} catch (Throwable e) {
   throw new CommandExecutorException(e);
}
  • many catch blocks one for each Exception. For example:
} catch (ClassCastException e1) {
   ...
} catch (FileNotFoundException e) {
   ...	
} catch (IOException e) {
   ...
}

The first approach is very compact but basically groups every exception in the same case, it's useful only in the situation where all the exceptions are managed equally and do the same thing, for example they bubble up to the view and become a message to the user. This approach is generally discouraged as it gives no control on the exceptions being catched, leading sometimes to tough bugs, which are also hard to find.

The second approach requires more lines of code but you can execute different operations depending on the exception occurred. This approach is more flexible but in some cases leads your methods to be very long due to exception handling. This is normally the most accepted way of catching exceptions.

If you use properly the encapsulation, relevancy and the Scoping principles you should already mitigate a lot this problem, and you should not have too long series of catch blocks.

Scoping

How long should a try block be? Should you write a try-block for a whole method or a try block for each single operation throwing something?

If you write too few try-blocks you risk your exception not to be meaningful and it won't help you to understand what's the problem when debugging. On the other hand if you write too many try-blocks. you end up with your code cluttered with exception management code, variables with strange scope and other ugly situations.

Once again the best solution is in the middle. Try to use try blocks wisely, grouping operations cleverly in order to balance the simplicity of your code, with the granularity of your exception management. I recommend minding the following consideration:

Use the try-blocks to enhance the scoping of your variables.
If you have a variable used only in a small part of your method, then you can use the try-block to delimit it's scope.
Use try-blocks to delimit your operations
You can split your code in several try catch blocks where each try is doing something specific. This delimitations make your code more readable.
Granularity of your exception handling
If you want your program to handle the exception in a very granular way, by catching every single exception and doing something appropriate with it. Then you probably want also to know exactly which operation generated it. You lose this information if you have more operations in one try-block.
Size of your code
It's normally better to write each block of code so that it can be seen all together on the screen. So if you write a method which is too long (you shouldn't really though) you can use the try-blocks to split the code to make it easier to read.
Number of exceptions thrown
This links to the Balance what you catch principle, where you want also to reduce the number of catches after a try-block in order to make your code easier to read.

If you balance the dimension of your try-blocks keeping in mind these considerations you should obtain a code elegantly written and easily readable.

Use Finally

Very often Programmers forgot about the finally block that you can attach to the try catch blocks.

The finally block is some code that it's executed anyway if the try block is successful or if an exception was thrown. This is very important when you are dealing with system resources, such files or database connections. If an exception was thrown (and normally you can't really be sure when to expect it) then it can happen that you may miss to execute some clean up code and leave resources allocated, or objects in an inconsistent state.

you can see it in action in the following example (from Split File :

FileWriter output= null;
try {
    output = new FileWriter(file);
    output.write(stringBuffer.toString());
    System.out.println("file " + path + filename + " written");
} catch (IOException e) {
    e.printStackTrace();
} finally {
    try {
      output.close();
    } catch (Throwable e) {
      e.printStackTrace();
    }
}

The side effect is that very often you end up needing to nest try&catch blocks within the finally blocks. There's a danger here because you could write:

try {
   output.close();
} catch (IOException e) {
   e.printStackTrace();
}

but this would collide with the catch (IOException e) outside the finally and generate dangerous, hard to debug situations.

Throw only Exceptions

In Java you can throw just anything, you are not bound to throw Exceptions. If you create your own class and extend the java.lang.Throwable class to make your class throwable and able to be handled in the same way as other exceptions or errors. But Throwable was thought specifically for error and exception handling, it's better to stick to that and not use this mechanism for other purposes. Forgetting this principle would drastically reduce the readability of your code and lead you to potential debugging nightmares.

Throw early catch late

This is probably the most famous principle about Exception handling. It basically says that you should throw an exception as soon as you can and catch it late, wait until you have all the information to handle it properly.

This principle implicitly says that you will be more likely to throw it in the low level methods, where you will be checking if single values are null or not appropriate. And you will be making the exception climb the stack trace for quite several levels until you reach a sufficient level of abstraction to be able to handle the problem. Ultimately you may reach the GUI to ask the user what to do, or even to the main, and manage a neat exit of the program.

Add validation

At some points in your application you know what to expect, and you generally assume that your inputs are correct. It's sometimes a good idea to to double check your inputs, to make sure that they are what you expect and throwing and exception if they are not. This is useful because it makes obvious by reading the code what you expect at specific points, so it increases the readability, plus it create some fixed points that alert you if during the execution something went wrong.

For example a validation I do quite often is similar to the following:

if ( null == variable || variable.isEmpty()){
   throw new blahException("the variable cannot be null at this point");
}

It's not necessary to be maniac about this, and clutter your code with variable validations. A good rule I follow is to add these validations whenever I'm solving a bug, in this way if the bug gets introduced again, I can spot it quickly.


Comments from the users

To be notified via mail on the updates of this discussion you can login and click on watch at the top of the page

Nice tips

Thx for this article, very interesting !

Jmix from http://lexique-du-net.com/blog/

--193.54.225.89 12:04, 14 January 2009 (UTC)


Encapsulation VS "Throw early catch late"

Nice article!

In layered architecture such as web -> service -> repository(dao) these two principles i.e Encapsulation and "Throw early catch late" some how seem to conflict. It makes sense to for each layer to encapsulate exception and throw it further. For example service layer will catch repository specific exceptions and encapsulate these with service exception and throw it to web layer. However this defeats the principle of "CATCH LATE" and some times just becomes an over head. Any thoughts/work arounds?

Thanks, Mohit Manrai

--193.130.13.233 12:06, 14 January 2009 (UTC)


Encapsulation VS "Throw early catch late"

Thank you Mohit.

Thanks for your comment. I think when you are doing encapsulation you are not really catching the exception but just forwarding it to the next level, and leaving a trace of where the exception has passed by. The real catch happens when you really do something with it and don't forward the exception any more.

I don't think nesting all these exceptions is an overhead, consider the case where you are using a DAO interface which is implementation independent and you can't sayif the DAO will access a local DB, a remote DB or even a plain XML file.

From the point of view of the client of the DAO it doesn't make sense to be catching several exceptions like UnableToConnectException, FileNotFoundException or SQLExceptions. Catching all these would be the real overhead.

Your DAO may be able to deal with these exceptions and catch them straight there. Or it may be not able to solve them and just pop them up encapsulated for example into a DAOException. The DAOException would climb up the levels until it gets to a method able to deal with it (throw early catch late). Thanks to encapsulation this method would easily get the list of Exceptions nested and thus know where the exception has passed by and have great detail on what went wrong. In complex situations this may result useful because he may get the similar exceptions from different contexts and be able to find the best solution.

For example if a method catches a ShapeException thrown by some method called in its body, it may be interesting to know what shape was causing the problem if it was a triangle or a square. Plus it may be useful to know if it was in a box or in a notebook if the triangle was in a box or in a notebook. it may be:

  • ShapeException->BoxException->TriangleException or a
  • ShapeException->NotebookException->TriangleException

using encapsulation in this way you can have all the information you need about the exception directly inside the exception. This doesn't add too much complexity, and in the event your program will grow in dimensions, you have a very scalable exception handling mechanism in place. Hope this answers your question.

--DonGiulio 12:20, 14 January 2009 (UTC)


RE: Encapsulation VS "Throw early catch late"

Mohit Manrai : Encapsulating exceptions just because we want to encapsulat it, is not a good practice, and leads to overhead you had mentioned. We want to encapsulate exceptions, because we want to hide the details of inner implemenation from the outside:

   - we do not want to make compile-time dependences to exceptions declared in some inner libraries/layers we depend
   - we want to leave us freedom of change the details of inner implemantation, and used libraries/layers. Declaring exceptions from inner libraries in interface methods would stick us to those libraries.

Encapsulate, if one of the above criteria is meet.

"catch late" does not mean literally 'catch' in this sentence. It is more like 'serve' - do some concrete response to the unexpected situaltion reported by the exception. This does not mean 'catch, encapsulate and throw'.

By the way, who knows why the above example of "use finally" is an antipattern? Because, in this wrongly coded example, any exception thrown by new FileWriter(fileName) would be hidden by NullPointerException throw from line 'output.close()'. This is not the worst case, because we used e.printStackTrace() before. At least we will have any log in the console. More danger would be, when we would use encapsulation instead of e.printStackTrace() - than, original exception would be lost.

Best Regards Marcin Sarniak Isolution Java Blog


--89.76.110.14 13:26, 14 January 2009 (UTC)



RE: Encapsulation VS "Throw early catch late"

Marcin: how would you solve that antipattern?
thanks & regards, --DonGiulio 13:51, 14 January 2009 (UTC)

Marcin Sarniak

First two thoughts:

If (output != null) {
   output.close()
}

or

catch (Throwable th) in finally <-- in finally designed to clean resources, with none specific business logic, it is acceptable, because safer: does not hide the primary exception.

--89.76.110.14 14:03, 14 January 2009 (UTC)


Good Thank you Marcin. Where would you put the if in your first thought? I updated the article with your second solution.

thanks, --DonGiulio 14:14, 14 January 2009 (UTC)


Response

Hello, In my first proposed sollution, I was thinking of:

try {
    if (output != null) {
       output.close();
    }
} catch (IOException e) {
   e.printStackTrace();
}

BR, Marcin Sarniak http://blog.isolution.pl

--89.76.110.14 16:11, 14 January 2009 (UTC)


Thanks

Thank you DonGiulio & Marcin for your response

Mohit Manrai

--193.130.13.233 16:50, 15 January 2009 (UTC)


GD2

I believe the best way is to explicitly throw a custom exception when ever the user needs to be informed of a undesired event - like zero balance in case of a banking checkout system etc. For all other cases, its best to catch the exception and log it and throw a new runtime exception (preserving the stack trace) and catch it at a central handler. This would remove a lot of boiler plate code in the whole project.

--GD2 09:53, 4 April 2011 (PDT)

tuna tore

very good article thanks

--tuna tore 14:19, 6 June 2011 (PDT)


Jaycee

Alakazaam-information found, problem solved, tnhaks!

--Jaycee 03:17, 18 August 2011 (PDT)


Comments on wikijava are disabled now, cause excessive spam.