The Google App Engine SDK uses checked exceptions on many of its API
methods. In many cases, I want to catch these exceptions and do
something Clojure-friendly with them. With Clojure 1.2.x, I had no
trouble catching checked exceptions by type, e.g.:
(try
(some-app-engine-api-methods-called-here ...)
(catch EntityNotFoundException ex ...))
This stopped working in 1.3.0. The caught exception does not match
EntityNotFoundException; it is now a RuntimeException with the
original typed exception chained to it.
I don't fully understand the implications of the exception handling
changes in 1.3 (https://github.com/clojure/clojure/commit/
8fda34e4c77cac079b711da59d5fe49b74605553). Does it mean that all
exceptions coming in from Java code into Clojure will now be wrapped
in an extra RuntimeException?
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clo...@googlegroups.com
> Note that posts from new members are moderated - please be patient with your
> first post.
> To unsubscribe from this group, send email to
> clojure+u...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
--
And what is good, Phaedrus,
And what is not good—
Need we ask anyone to tell us these things?
This caused me some pain in clojure.java.jdbc and I actually catch
RuntimeException inside the library and unwrap it and throw the
underlying SQLException (for transactions):
;; This ugliness makes it easier to catch SQLException objects
;; rather than something wrapped in a RuntimeException which
;; can really obscure your code when working with JDBC from
;; Clojure... :(
(letfn [(throw-non-rte [ex]
(cond (instance? java.sql.SQLException ex) (throw ex)
(and (instance? RuntimeException ex)
(.getCause ex)) (throw-non-rte (.getCause ex))
:else (throw ex)))]
(throw-non-rte e)))
I've had to do similar things in my own code to get at the underlying
exceptions...
It would be much, much friendlier to have (try .. (catch ..))
automatically unroll RuntimeException "on demand" so the "obvious"
code works.
--
Sean A Corfield -- (904) 302-SEAN
An Architect's View -- http://corfield.org/
World Singles, LLC. -- http://worldsingles.com/
Railo Technologies, Inc. -- http://www.getrailo.com/
"Perfection is the enemy of the good."
-- Gustave Flaubert, French realist novelist (1821-1880)
the problem is in Reflector.java and the call to Class/forName is
non-reflective, so of course it doesn't expose the problem.
I understand _why_ the change to wrap exceptions was made but without
the equivalent unwrapping in try/catch this just moves the pain from
the library/language out to the users, yes?
Sean
The change merely owned up the the fact that we cannot in fact communicate all actual errors through Java code, due to checked exceptions. This is an enduring problem with Java, and you are going to see it rear its ugly head in Java itself as soon as Java gets some closure-like construct.
We can of course add some unwrapping to try/catch, and could have for 1.3, had anyone who currently cares about this tried the code and acted sooner. Patch welcome for 1.4. Note the handling will have to be careful not to unwrap too much, as some people care about cause chains and not just root causes.
Rich
--
I've done something like this in Java projects but without any magic unwrapping. It worked well. Manual unwrapping wasn't too onerous in the rare cases where we wanted to do so. The Clojure-specific exception should be part of the public API for Java interop. Don't try to hide it.
The problem - in Clojure code using try/catch - is that you don't know
whether the real exception will be wrapped or not (because you may be
calling thru some intermediate layer that may or may not do
reflection) therefore you cannot usefully catch a given exception in
Clojure: you will _always_ have to catch both the intended exception
*and* catch ClojureRTException and unroll it yourself with the same
code in both branches of logic. That's _horrible_.
try/catch should do the unrolling for you - esp. if we introduce
ClojureRTE as a wrap-only exception so it won't be confused with a
regular RTE.
On Oct 12, 2011, at 1:21 PM, Sean Corfield wrote:
> On Wed, Oct 12, 2011 at 7:37 AM, Stefan Kamphausen
> <ska...@googlemail.com> wrote:
>> To my humble ears this sounds like the best idea so far. Something like
>> ClojureRTException ...
>
> The problem - in Clojure code using try/catch - is that you don't know
> whether the real exception will be wrapped or not (because you may be
> calling thru some intermediate layer that may or may not do
> reflection) therefore you cannot usefully catch a given exception in
> Clojure: you will _always_ have to catch both the intended exception
> *and* catch ClojureRTException and unroll it yourself with the same
> code in both branches of logic. That's _horrible_.
>
> try/catch should do the unrolling for you - esp. if we introduce
> ClojureRTE as a wrap-only exception so it won't be confused with a
> regular RTE.
I had read the idea as implying that try/catch would implicitly always catch RTE, unwrap it, and give your "real" catch body a chance to catch that…
- Chas
I'm not incredibly experienced with Java, but would using a Java
construct which tricks the language into allowing unchecked exceptions
be too crazy? I've seen references to both of these approaches, but
haven't actually tried either for anything:
http://james-iry.blogspot.com/2010/08/on-removing-java-checked-exceptions-by.html
http://projectlombok.org/features/SneakyThrows.html
The former even came up on #clojure, I believe.
-Marshall
http://dev.clojure.org/jira/browse/CLJ-855
// Ben
seems like refactoring Reflector.java to rethrow using this approach
is preferable to some wrapping/unwrapping scheme
> http://projectlombok.org/features/SneakyThrows.html
>
> The former even came up on #clojure, I believe.
>
> -Marshall
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clo...@googlegroups.com
> Note that posts from new members are moderated - please be patient with your first post.
> To unsubscribe from this group, send email to
> clojure+u...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
--