sneaky throws/exception enrichment

237 views
Skip to first unread message

Stephen Haberman

unread,
May 18, 2011, 2:22:03 PM5/18/11
to omaha-java-...@googlegroups.com
Hey,

Exception handling came up in the discussion last night. "Sneaky
throws" is a technique I mentioned that let's you avoid wrapping
checked exception in RuntimeExceptions, creating more nested
stack traces than you need. See:

http://www.mail-archive.com/java...@googlegroups.com/msg05984.html

You can do:

public void foo() {
try {
doSomethingSql();
} catch (SQLException s) {
throw sneakThrows(s);
}
}

Note there is no "throws SQLException" declared for foo, and yet
the exception instance "s" will not be wrapped with a
RuntimeException.

And, yes, Dave, lombok has some magic for this too, so you can
even replace the try/catch with an annotation:

http://projectlombok.org/features/SneakyThrows.html

A few other guys reported success with enrichment exceptions,
when also seem like a nice way to avoid reams of redundant
stack traces in your log output:

http://tutorials.jenkov.com/java-exception-handling/exception-enrichment.html

- Stephen

snekse

unread,
May 19, 2011, 11:14:01 AM5/19/11
to omaha-java-...@googlegroups.com
I want to talk more about lombok - that's pretty sweet.


--
You received this message because you are subscribed to the Google Groups "Omaha Java Users Group" group.
To post to this group, send email to omaha-java-...@googlegroups.com.
To unsubscribe from this group, send email to omaha-java-users-...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/omaha-java-users-group?hl=en.


Stephen Haberman

unread,
May 20, 2011, 3:26:41 PM5/20/11
to omaha-java-...@googlegroups.com

> I want to talk more about lombok - that's pretty sweet.

Yeah, no kidding. Speaking of exceptions, here's another insane
lombok hack:

http://projectlombok.org/disableCheckedExceptions.html

https://groups.google.com/forum/#!topic/javaposse/Am7ADgYBAj0

During the compile, they reflect into the javac code itself, find the
method that detects whether you have "throws Xxx" clauses for all of
the method calls that throw checked exceptions and just replaces the
whole method with "return true".

Crazy.

They've only accomplished it in javac though (not Eclipse),
so it's not a fully supported lombok feature.

- Stephen

Matthew Heller

unread,
May 20, 2011, 4:32:36 PM5/20/11
to omaha-java-...@googlegroups.com
> Exception handling came up in the discussion last night. "Sneaky
> throws" is a technique I mentioned that let's you avoid wrapping
> checked exception in RuntimeExceptions, creating more nested
> stack traces than you need. See:
>
> http://www.mail-archive.com/java...@googlegroups.com/msg05984.html

> Note there is no "throws SQLException" declared for foo, and yet


> the exception instance "s" will not be wrapped with a
> RuntimeException.

The sneakyThrows0 method seems to cast the incoming <T extends Throwable> as a RuntimeException, but if you put that in a try block and catch RuntimeException, it slips right through.

try {
try {
throw new IOException();
} catch (IOException e) {
Sneak.sneakyThrow(e);
}
} catch (RuntimeException e) {
// It slips through and doesn't trigger this!
return;
} catch (Throwable t) {
fail(); // we fail it. :-(
}

However, if I change sneakyThrows0 to cast/throw RuntimeException rather than T, it triggers the RuntimeException block as I expected.

Alternatively, changing sneakyThrows0 such that T extends Exception (or MySpecialBaseException, etc) WILL allow you to catch Exception (or etc) and handle from there.

Type erasure, maybe you're not so bad after all. ;-)

-Matt

Stephen Haberman

unread,
May 20, 2011, 5:19:39 PM5/20/11
to omaha-java-...@googlegroups.com

> The sneakyThrows0 method seems to cast the incoming <T extends
> Throwable> as a RuntimeException, but if you put that in a try block
> and catch RuntimeException, it slips right through.

Yeah, that is a downside of the approach. I do remember myself adding
"catch RuntimeException" blocks thinking "ah, a checked exception can
never happen here". Perhaps that is not such a smart idea given checked
exceptions are a compiler-only enforcement that is circumventable.

> However, if I change sneakyThrows0 to cast/throw RuntimeException
> rather than T, it triggers the RuntimeException block as I expected.

It triggers the RuntimeException block, but when I try it, it's because
casting to a RuntimeException leads to a new ClassCastException being
thrown and not the original IOException.

> Type erasure, maybe you're not so bad after all. ;-)

:-)

Also, you could potentially write:

try {
throw new IOException("bad");
} catch (final IOException e) {
throw sneakyThrow(e);
}

With an added "throw" before the "sneakyThrow(e);" so that the compiler
will, say, let you not have a return after the sneakyThrow line.

- Stephen

Matthew Heller

unread,
May 20, 2011, 5:29:48 PM5/20/11
to omaha-java-...@googlegroups.com
> It triggers the RuntimeException block, but when I try it, it's because
> casting to a RuntimeException leads to a new ClassCastException being
> thrown and not the original IOException.

But the test turned green!!!111 (Nice catch.)

> try {
> throw new IOException("bad");
> } catch (final IOException e) {
> throw sneakyThrow(e);
> }
>
> With an added "throw" before the "sneakyThrow(e);" so that the compiler
> will, say, let you not have a return after the sneakyThrow line.


Oh, that makes a lot more sense. Otherwise there would be no point in it having a return value.

Thanks,
-Matt

Reply all
Reply to author
Forward
0 new messages