Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Auto logging in catch block, only when exception variable is annotated, for Java or Kotlin

I want to do this for Java or Kotlin: given the code below

try { ...
} catch (@AutoLog e: Exception) { //position1
}

add a logging statement at position1 automatically during build time. I can add code with AspectJ for catch block(for both Java and Kotlin), but it's for all catch blocks, I can't check whether @AutoLog annotation is present and add code only when it is. So I think I have to turn to APT(Annotation processing tool) for Java (or KAPT for Kotlin)?

Btw, I found a KAPT code generation example here: https://github.com/JetBrains/kotlin-examples/tree/master/gradle/kotlin-code-generation , but it generates code to separate file, while what I want to do is modify the original file/class and add a statement in catch block.

like image 654
Jacob Wu Avatar asked Oct 08 '18 02:10

Jacob Wu


1 Answers

Instead of using annotations, you can use some of Kotlin's features to create your own functions that operate similarly to the standard try { ... } catch { ... }, but also log exceptions. Here's a quick example:

sealed class Result<S>

class Success<S>(val value: S) : Result<S>()
class Error<S, E : Throwable>(val error: E) : Result<S>()

fun <S> loggingTry(block: () -> S): Result<S> {
    return try {
        Success(block())
    } catch (e: Throwable) {
        Error(e)
    }
}

inline infix fun <reified E : Throwable, R> Result<out R>.catch(handler: (E) -> R): R {
    return when (this) {
        is Success -> value
        is Error<*, *> -> if (error is E) {
            println("Error $error is being handled") // replace this with your own logging
            handler(error)
        } else throw error
    }
}

fun main(args: Array<String>) {
    val x = loggingTry {
        1 / 0
    } catch { e: ArithmeticException ->
        3
    }

    println("Result: $x")

    loggingTry {
        1 / 0
    } catch { e: NullPointerException ->
        println("This won't be called, the exception will just be re-thrown")
    }
}

This code generates the following output:

Error java.lang.ArithmeticException: / by zero is being handled
Division result was 3
Exception in thread "main" java.lang.ArithmeticException: / by zero
    at MainKt$main$1.invoke(Main.kt:34)
    at MainKt$main$1.invoke(Main.kt)
    at MainKt.loggingTry(Main.kt:8)
    at MainKt.main(Main.kt:33)

This isn't a perfect solution, since it's more limited (e.g. no multi-catch) and has a slightly different syntax, but the end result is comparable.

like image 164
apetranzilla Avatar answered Oct 10 '22 19:10

apetranzilla