I came across this kind of exception handling code.
import java.util.Observable; import java.util.Observer; public class Framework extends Observable { public void SendMessage(String msg) { setChanged(); try { notifyObservers(msg); } catch (RuntimeException re) { throw new RuntimeException("Something bad happend."); } } public static void main(String[] args) { Framework f = new Framework(); f.addObserver(new Observer() { @Override public void update(Observable o, Object arg) { System.out.println("I am fine: " + arg.toString()); } }); f.SendMessage("hello world"); } }
This is pretty common pattern. Right? You create a list of several instances and iterate over them to do something. Actually, that’s the beautiful pattern commonly used.
But, the code actually has a pitfall. Look at the error handling part. Can you identify it?
try { notifyObservers(msg); } catch(RuntimeException re) { throw new RuntimeException("Something bad happend."); }
At first glance, this looks fine. It’s trying to tell something to the user. It’s not even swallowing the exception. But that’s not all for the framework developer. What happens if I add an innocent observer but got some error?
public static void main(String[] args) { Framework f = new Framework(); f.addObserver(new Observer() { @Override public void update(Observable o, Object arg) { System.out.println("I am fine: " + arg.toString()); } }); f.addObserver(new Observer() { @Override public void update(Observable o, Object arg) { throw new RuntimeException("I got an error: " + arg.toString()); } }); f.SendMessage("hello world"); }
Now the code spits out this:
Exception in thread “main” java.lang.RuntimeException: Something bad happend.
at Framework.SendMessage(Framework.java:11)
at Framework.main(Framework.java:29)
Seriously, that’s all I get. If this happens, I’m left with no clue but something went wrong.
Please do not swallow not just your exception but also your stack trace. How can I believe that all other observers are fine but it’s just my fault without any proof?
Keep the stack trace:
try { notifyObservers(msg); } catch (RuntimeException re) { throw new RuntimeException("Something bad happend.", re); }
Now I get this awesome trace:
Exception in thread “main” java.lang.RuntimeException: Something bad happend.
at Framework.SendMessage(Framework.java:11)
at Framework.main(Framework.java:29)
Caused by: java.lang.RuntimeException: I got an error: hello world
at Framework$2.update(Framework.java:26)
at java.util.Observable.notifyObservers(Unknown Source)
at Framework.SendMessage(Framework.java:9)
… 1 more