MINOR: Catch InvocationTargetException explicitly and propagate underlying cause#12230
Conversation
46f1013 to
73afd1b
Compare
|
@dengziming @showuon please review this small change. |
ijuma
left a comment
There was a problem hiding this comment.
Thanks for the PR, left a couple of comments.
There was a problem hiding this comment.
Have we checked that changing this exception doesn't cause an issue?
There was a problem hiding this comment.
Yes. This method is only used in trogdor today and there is no specific handling of ClassNotFoundException exception.
There was a problem hiding this comment.
Could we throw ClassNotFoundException like before, and pass e.getCause() to it instead? I think throwing ClassNotFoundException for consistency is better.
There was a problem hiding this comment.
Wouldn't a ClassNotFoundException be wrong in this context and give a wrong impression to user? I am saying this because it's not a problem with Class not being on the JVM's classpath, instead InvocationTargetException is thrown when we have found the Class and invoking the constructor is throwing an exception in the line constructor.newInstance(args
I am happy to replace KafkaException with other generic RuntimeException that you would suggest but ClassNotFoundException appears inappropriate to me.
There was a problem hiding this comment.
Good point! You're right! When entering here, the constructor is already found and called, just there's exception thrown. Let's keep KafkaException like you did. Thank you.
There was a problem hiding this comment.
True, but I would disagree that it is a downside.
In my opinion, a caller should be handling the underlying cause because the InvocationTargetException is being thrown from business logic inside the constructor. If the caller catches a generic ReflectiveOperationException it doesn't get to know (without inspecting details) whether the exception is due to a "reflection op error" such as method not found, class not found etc. or whether it is an exception thrown by the business logic itself. I believe that propagating the underlying business logic exception is better in this scenario.
Having said that, I don't have a strong opinion on this one as it's a minor improvement that will only impact code debuggability when looking at exception traces. Happy to revert if you think otherwise.
There was a problem hiding this comment.
I also agree with @divijvaidya here, having a strong distinction between business logic and reflection based exceptions is ideal and in my opinion over the long term is less brittle (since if you catch business logic exceptions that is unlikely to change)
There was a problem hiding this comment.
The caller may be itself generic code. For example, see what happened here:
The method now throws Throwable. It was pretty hard for me to say whether we needed to update some code to handle other exceptions. Is it clear to you?
There was a problem hiding this comment.
@ijuma , thanks for the explanation. Make sense to me.
@divijvaidya I think it's better we revert it. WDYT?
|
@mimaison kindly review when you get a chance. |
mdedetrich
left a comment
There was a problem hiding this comment.
The changes look good from my end
|
@showuon requesting for your code review time on this one. We already have two approvals from non-committers. |
2d8dda6 to
d7eab2d
Compare
|
The failing tests for JDK 11 are unrelated to the code changes. @ijuma @mimaison requesting your your time to review this. Please note that we have this triaged with two non-committers already. |
showuon
left a comment
There was a problem hiding this comment.
@divijvaidya , sorry for the delay. Overall LGTM, left one comment.
There was a problem hiding this comment.
Could we throw ClassNotFoundException like before, and pass e.getCause() to it instead? I think throwing ClassNotFoundException for consistency is better.
InvocationTargetException always wraps an underlying cause. It makes sense to catch it as soon as possible and only propagate the underlying cause.
Change
getCause()[1] "legacy as per the docs" https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/InvocationTargetException.html