Here is part of code I wrote once:
String execute(String data) { String result = null; try { final Execute execute = new Execute(); execute.setId(id); execute.setData(data); result = cmiss.execute(execute).getData(); } catch (RemoteException e) { e.printStackTrace(); } catch (CommandFault e) { e.printStackTrace(); } finally { return result; } }
After adding proper exception handling it becomes this:
String execute(String data) { String result = null; try { final Execute execute = new Execute(); execute.setId(id); execute.setData(data); result = cmiss.execute(execute).getData(); } catch (RemoteException e) { throw new LogicError("Cmiss: " + e.getMessage()); } catch (CommandFault e) { throw new LogicError("Cmiss: " + e.getMessage()); } finally { return result; } }
At this point Eclipse start complaining about the finally
block saying that
finally block does not complete normally
and proposing
Add suppressWarnings `finally` to execute()
as the only possible solution.
While everything was working fine I didn’t care about what Eclipse says until
one day something went wrong, but code on layers above execute()
didn’t get
any exceptions. This was something I didn’t expect at all, so I started the
debugger and saw that exception is throws as it should be, but then it gets
“swallowed” by the finally
block. But wait, the method doesn’t have
exception list at all, java compiler silently compiles such code because it
knows that with finally
block containing return
statement in it, no
exception will be thrown. Unfortunately I didn’t know that before.
Now code looks like this and works as expected:
String execute(String data) throws LogicError { String result = null; try { final Execute execute = new Execute(); execute.setId(id); execute.setData(data); result = cmiss.execute(execute).getData(); } catch (RemoteException e) { throw new LogicError("Cmiss: " + e.getMessage()); } catch (CommandFault e) { throw new LogicError("Cmiss: " + e.getMessage()); } return result; }