I'm going to develop an open-source Exceptor that helps me do exceptionHandling very conveniently in Rest Controller.
It is used in a typical way as follows,
@GetMapping
fun getExample(): ResponseEntity<Any> {
exampleReader.readBy().orElseThrow{ IllegalArgumentException("test") }
return ResponseEntity.ok(null)
}
@ExceptionHandler(IllegalArgumentException::class)
@ResponseStatus(HttpStatus.NOT_FOUND)
fun onException(e: IllegalArgumentException): ErrorResponse {
return ErrorResponse.with(HttpStatus.NOT_FOUND.value(), e.message)
}
I would like to provide it very conveniently in the following format.
@GetMapping
@Exceptor(status = HttpStatus.NOT_FOUND, exception = IllegalArgumentException::class)
fun getExample(): ResponseEntity<Any> {
exampleReader.readBy().orElseThrow{ IllegalArgumentException("test") }
return ResponseEntity.ok(null)
}
I implemented the Exceptor Processor after creating the Exceptor Annotation, but it doesn't work. What's the problem?
@AutoService(Processor::class)
class ExceptorProcessor : AbstractProcessor() {
override fun getSupportedAnnotationTypes(): Set<String> {
return setOf(Exceptor::class.java.canonicalName)
}
override fun getSupportedSourceVersion(): SourceVersion {
return SourceVersion.latestSupported()
}
override fun process(annotations: Set<TypeElement>, roundEnv: RoundEnvironment): Boolean {
for (element in annotations) {
if (element.kind == ElementKind.METHOD) {
val methodElement = element as ExecutableElement
processAnnotatedMethod(methodElement)
} else {
processingEnv.messager.printMessage(
Diagnostic.Kind.ERROR,
"@Exceptor can only be applied to methods.",
element
)
}
}
return true
}
private fun processAnnotatedMethod(methodElement: ExecutableElement) {
val annotation = methodElement.getAnnotation(Exceptor::class.java)
val status = annotation.status
val exceptionClass = annotation.exception.java
val methodName = methodElement.simpleName.toString()
val enclosingClass = methodElement.enclosingElement.simpleName.toString()
val exceptionHandlerAnnotation = ExceptionHandler::class.java.canonicalName
val responseStatusAnnotation = ResponseStatus::class.java.canonicalName
val generatedCode = """
@$exceptionHandlerAnnotation(${exceptionClass.simpleName}::class)
@$responseStatusAnnotation($status)
fun onException(e: ${exceptionClass.simpleName}): ErrorResponse {
return ErrorResponse.with($status.value(), e.message)
}
""".trimIndent()
processingEnv.messager.printMessage(Diagnostic.Kind.NOTE, "Generated code:\n$generatedCode")
}
}
I referred to the reference, but it was hard to find why the process didn't work.
I tried to interact in a different way, but my knowledge was not enough.
I can't speak English well, so I get help from a translator.
How can I implement it properly? Please give me a lot of advice on the intercept method or the way the process is called. Thank you.