Skip to content

RestBuilder violates Vert.x 4.3's handler ordering #134

@ghost

Description

Description

Since vert.x 4.3 the order in which routes are registered is checked by io.vertx.ext.web.impl.RouteState.
Using rest.vertx with vert.x 4.3 can lead to an error in specific circumstances:

Exception in thread "main" java.lang.IllegalStateException: Cannot add [BODY] handler to route with [USER] handler at index 0
	at io.vertx.ext.web.impl.RouteState.addContextHandler(RouteState.java:554)
	at io.vertx.ext.web.impl.RouteImpl.handler(RouteImpl.java:143)
	at com.zandero.rest.RestRouter.register(RestRouter.java:152)
	at com.zandero.rest.RestRouter.register(RestRouter.java:70)
	at com.zandero.rest.RestBuilder.getRouter(RestBuilder.java:497)
	at com.zandero.rest.RestBuilder.build(RestBuilder.java:570)

This can be circumvented by setting the io.vertx.web.router.setup.lenient property to true, but even then a WARNING is logged.

As far as I could tell, this issue occurs

  • When the request body is present in the function parameters
  • When context (e.g. User) is present in the function parameters

Resolution suggestions

From a cursory glance, the "weight" of a handler is determined by its type. As such, a PlatformHandler should have the highest "priority". So a possible solution would be to mark the custom handlers that are registered before the body handler as implements io.vertx.ext.web.handler.PlatformHandler.

If no marker interface is implemented, priority "USER" is assumed (lowest priority -> register last).

Steps to reproduce

Setup minimal vert.x app with a sample resource

fun main() {
    val vertx = Vertx.vertx()
    val router = RestBuilder(vertx)
        .register(TestResource::class.java)
        .build()
    vertx.createHttpServer().requestHandler(router).listen(8080)
}

@Path("/test")
class TestResource {
    @POST
    fun postFoo(requestBody: String) = requestBody

    @GET
    fun getFoo(@Context user: User?) = "${user?.subject()}"
}

Use vert.x 4.3+ and rest.vertx 1.1

dependencies {
    implementation(platform("io.vertx:vertx-stack-depchain:4.3.3"))
    implementation("io.vertx:vertx-web")
    implementation("com.zandero:rest.vertx:1.1")
}

Run app:

Exception in thread "main" java.lang.IllegalStateException: Cannot add [BODY] handler to route with [USER] handler at index 0
	at io.vertx.ext.web.impl.RouteState.addContextHandler(RouteState.java:554)
	at io.vertx.ext.web.impl.RouteImpl.handler(RouteImpl.java:143)
	at com.zandero.rest.RestRouter.register(RestRouter.java:152)
	at com.zandero.rest.RestRouter.register(RestRouter.java:70)
	at com.zandero.rest.RestBuilder.getRouter(RestBuilder.java:497)
	at com.zandero.rest.RestBuilder.build(RestBuilder.java:570)
	at rest.vertx.repro.AppKt.main(App.kt:10)
	at rest.vertx.repro.AppKt.main(App.kt)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions