What is wrong with my Exceptor in kotlin?

46 views Asked by At

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.

0

There are 0 answers