kotlinquarkusvert.xmutinyvertx-eventbus

Propagate Exceptions from Vert.x EventBus Consumer when using handlers


I am using Quarkus with the Mutiny adapter for Vert.X and would like to propagate Exceptions that happen in the consumer instead of having them wrapped in a io.vertx.core.eventbus.ReplyException, see https://quarkus.io/guides/reactive-event-bus#handling-failures.

I have a consumer like:

 @ConsumeEvent("foo")
    fun consume(object: MyCustomParameter): Uni<MyCustomResponse> = doAsyncWork.onFailure().transform { exception ->
                when (exception) {
                    is StrangeException -> ComprehensiveException(exception.message, 400)
                    is WeirdException -> NotFoundException()                
                    else -> WebApplicationException(exception)
                }

When I now call request:

@ApplicationScoped
class Bean(
    private val eventBus: EventBus
) {

  fun bar() {
        eventBus.request<MyCustomResponse>("foo", someObj).onFailure().invoke { exception ->
          print(exception) // <--- This is always a ReplyException, should be one of the exceptions above
        }
    }
}

I've tried injecting vertx directly and creating the eventbus from there and setting the exception handler to null. I've followed these tests from the quarkus repo.

Since this had no effect I've read the link that I posted more thoroughly and noticed the handler does this kind of magic under the hood. I'll will later try using the vertx object to handle the response manually, but it seems like it's backed into the Mutiny adapter of Vert.X or Vert.X directly.


Solution

  • The reason for Vert.x swallowing the original exception is serialization: EventBus messages can be sent inside the same JVM, from one JVM to another in a cluster or even from some other runtime like Python or JavaScript to JVM.

    Vert.x needs to be able to serialize an exception in order to be able to send it over the network. We're not talking about Java Serializable btw.

    Vert.x 5, arriving later this year, will provide a constructor on ReplyException which accepts a cause exception, see here. However, you will need a custom message codec as soon as you deploy your app in a cluster.