How do you handle exceptions in WorkActions? I hav...
# plugin-development
t
How do you handle exceptions in WorkActions? I have a WorkAction that runs in a classLoaderIsolation or processIsolation WorkQueue, the code inside the WorkAction can throw exceptions. One of these exceptions (from a third-party library) computes its
getMessage()
lazily using a helper class (from that same third-party lib). The problem is that, if I don't do anything special, Gradle will somehow "copy" the exception outside of the classLoaderIsolation or back to the Gradle Daemon process, but won't "copy" that helper class, so when Gradle wants to print the error message to the console and calls the exception's
getMessage()
method, that one will throw a ClassNotFoundException that will shadow the actual error. How would you recommend handling this?
1
I could simply creating a new exception type and "unwrap" the third-party exception and recreate a similar one? (
throw new MyException(e.getMessage(), e.getCause())
; possibly just using a RuntimeException, maybe prefixing), but there could be a similar issue in an exception in the stacktrace. I could also look just log the error and throw an exception without any relation to the possibly-problematic one.
Copy code
logger.error("…", e);
throw new RuntimeException("…"); // note: no cause here
Anything else? What would you recommend?
t
i don't have an answer, but that sounds like a Gradle bug. is there an open issue for it?
m
I don't think there is any "copy" involved? The problem is that the helper class isn't loaded and cannot be loaded by the classloader catching the exception?
Not sure if Gradle can/should handle that. I'm not 100% clear on what's happening but I would probably wrap any 3rd party exception with something that can be called from the caller classloader
Or maybe there is "copy" indeed and the worker do more stuff than what I was expecting 🤔 What makes you think there is a "copy"?
t
You're right I made wrong assumptions (and not enough testing). So, process isolation is not a problem actually, only classLoaderIsolation is; and indeed it might then just be a classloader "escape" issue, with no "copying" involved. That doesn't really change the initial question though 😉 (phew!) Apparently, just wrapping the exception with something as simple as
new RuntimeException(e)
is enough to make it work: when printing the stacktrace, the JVM is smart enough to run the
getMessage()
in the appropriate classloader so the helper class can be loaded without error 🤯 (and the runtime exception will have its message eagerly derived from the wrapped exception's toString, so the information is there too when stacktraces aren't printed)
til 2
m
Wow good find! Wrapping the exception sounds acceptable.
t
Fwiw, this worked too:
Copy code
try {
  …
} catch (ProblematicException e) {
  RuntimeException re = new RuntimeException(e.toString(), e.getCause());
  re.setStackTrace(e.getStackTrace());
  throw re;
}
Original exception class will be in the message (through toString), and stacktrace will be the same.
👌 1