Last active
January 26, 2023 11:21
-
-
Save rponte/8f23557d7e3079c9e644e620df293420 to your computer and use it in GitHub Desktop.
Micronaut: Implementing a Micronaut AOP Interceptor for exception handling in gRPC endpoints
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package br.com.zup.edu.shared.grpc | |
import io.grpc.BindableService | |
import io.grpc.stub.StreamObserver | |
import io.micronaut.aop.MethodInterceptor | |
import io.micronaut.aop.MethodInvocationContext | |
import org.slf4j.LoggerFactory | |
import javax.inject.Inject | |
import javax.inject.Singleton | |
/** | |
* Class responsible for intercepting gRPC Endpoints and handling any exception thrown by their methods | |
*/ | |
@Singleton | |
class ExceptionHandlerInterceptor(@Inject private val resolver: ExceptionHandlerResolver) : MethodInterceptor<BindableService, Any?> { | |
private val logger = LoggerFactory.getLogger(this::class.java) | |
override fun intercept(context: MethodInvocationContext<BindableService, Any?>): Any? { | |
try { | |
return context.proceed() | |
} catch (e: Exception) { | |
logger.error("Handling the exception '${e.javaClass.name}' while processing the call: ${context.targetMethod}", e) | |
val handler = resolver.resolve(e) | |
val status = handler.handle(e) | |
GrpcEndpointArguments(context).response() | |
.onError(status.asRuntimeException()) | |
return null | |
} | |
} | |
/** | |
* Represents the endpoint method arguments | |
*/ | |
private class GrpcEndpointArguments(val context : MethodInvocationContext<BindableService, Any?>) { | |
fun response(): StreamObserver<*> { | |
return context.parameterValues[1] as StreamObserver<*> | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package br.com.zup.edu.shared.grpc | |
import io.micronaut.aop.Around | |
import io.micronaut.context.annotation.Type | |
import kotlin.annotation.AnnotationTarget.* | |
@MustBeDocumented | |
@Retention(AnnotationRetention.RUNTIME) | |
@Target(CLASS, FILE, FUNCTION, PROPERTY_GETTER, PROPERTY_SETTER) | |
@Around | |
@Type(ExceptionHandlerInterceptor::class) | |
annotation class ErrorHandler() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@ErrorHandler // enables the interceptor for all methods | |
@Singleton | |
class KeyManagerEndpoint() : KeymanagerGrpcServiceGrpc.KeymanagerGrpcServiceImplBase() { | |
override fun registra( | |
request: RegistraChavePixRequest, | |
responseObserver: StreamObserver<RegistraChavePixResponse> | |
) { | |
throw IllegalArgumentException("Invalid request parameters"); // it will be handled as Status.INVALID_ARGUMENT by default | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Micronaut v2.4 changed the way it configures interceptors. Now, the interceptor class is responsible for setting which annotation(s) it works with via
@InterceptorBean