Reputation: 5858
I am working in a small feature for a Kotlin project and I am trying to do an annotation.
I want to "encapsulate" a method inside a try catch.
Lets say I annotate a method like this
@LogException
fun foo(){
//do something
}
So I want to process the annotation to later do something like this:
try{
foo()
}catch(exception: Exception){
// do something
//log
}
Is it even possible?
I started with tutorial for Kotlin (that should not be so different than Java) https://medium.com/@elye.project/annotation-tutorial-for-dummies-in-kotlin-1da864acc442 But then I am using this
@AutoService(Processor::class)
To register my processor and I think is not initializing my annotation.
So far this is my code:
@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.SOURCE)
@Documented
annotation class LogException(
val name: String,
val statusCode: Int = 500
)
and my processor:
@AutoService(Processor::class)
class MyProcessor : AbstractProcessor() {
val logger = LoggerFactory.getLogger(MyProcessor::class.java)
override fun process(annotations: MutableSet<out TypeElement>?, roundEnv: RoundEnvironment?): Boolean {
//do something
logger.info("info")
return false
}
override fun getSupportedAnnotationTypes(): MutableSet<String> {
logger.info("info")
return mutableSetOf(LogException::class.java.canonicalName)
}
}
At the moment I am not able to see any in my logs, or even if I change it for an exception.
I am using this annotation in a method.
@LogException
fun foo(){
//do something
}
Any idea what Im missing?
//do something and //log something is just example to dont paste all code
Upvotes: 1
Views: 1038
Reputation: 2492
It's not possible to change the existing code using annotation processors. They can only create new files. If you want to change existing ones, write Kotlin compiler plugin.
If you only want to get rid of boilerplate catch blocks, use an inline
function which wraps an original function with try-catch
:
inline fun runLogging(code: () -> Unit) = try {
code()
} catch (e: Exception) {
yourLogger.log(e)
}
fun foo() = runLogging {
throw Exception() // will be logged
}
Or you can make runLogging
generic function which handles only specified exceptions:
inline fun <reified E : Exception> runLogging(code: () -> Unit) = try {
code()
} catch (e: Exception) {
if (e is E) yourLogger.log(e)
else throw e
}
fun foo() = runLogging<FileNotFoundException> {
throw FileNotFoundException() // will be logged
}
fun bar() = runLogging<FileNotFoundException> {
throw Exception() // will be rethrown
}
Upvotes: 1