Home > front end >  In Groovy(/Java) how would I remove the current function from the stackTrace when throwing an Except
In Groovy(/Java) how would I remove the current function from the stackTrace when throwing an Except

Time:02-24

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.

https://docs.oracle.com/javase/7/docs/api/java/lang/Throwable.html#setStackTrace(java.lang.StackTraceElement[])

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

  • Related