I'd like to provide a function for throwing exceptions rather than throwing them directly. E.g. instead of writing:
def foo() {
def result = command_result("foo");
if (!result) {
throw new Exception("Bla!");
}
return result;
}
I'd like to write this:
def foo() {
return command_result("foo") ?: error("Bla!");
}
which requires a function error()
to be defined:
def error(msg) {
throw new Exception(msg);
}
But of course I now have error()
on top of the call stack, so if I wrote
try {
print(foo());
} catch(Exception error) {
print("ERROR: ${error.stackTrace.head()}: ${error}");
}
I'd get something like
ERROR: Script1.error(Script1.groovy:19): java.lang.Exception: Bla!
To get rid of error:19
on the stack I could just extract the second item on error.stackTrace
I guess but that would force me to have one generic try/catch
block.
Is it possible to provide such a functionality in Groovy (I guess it would be the same in Java) i.e. (re) throwing an Exception with the current function removed from the back trace?
CodePudding user response:
Use getStackTrace, then drop items you don't want to be there, then use setStracTrace to change it in exception.
in groovy it's quite hard to drop all stacktrace elements that belong to latest call. however you could sanitize stacktrace (remove all groovy internal items) before doing this:
def error(msg) {
def e = new Exception(msg)
e = org.codehaus.groovy.runtime.StackTraceUtils.sanitize(e)
//drop items with unknown source and drop first element of stacktrace
e.setStackTrace( e.getStackTrace().findAll{ it.getFileName() }.drop(1) as StackTraceElement[] )
throw e
}
def foo(x) {
return x ?: error("Bla!")
}
try{
foo(0)
}catch(e){
assert e.stackTrace[0].methodName=='foo'
e.printStackTrace()
}
Note: if you running this code in groovyconsole
the View / Show Full Stack Trace
menu item must be disabled to make sanitize
working