Vertx Web Resource Not Found

736 views Asked by At

In one of the projects that I'm working on I register routes onto the Router dynamically like below.

vertx.eventBus().consumer("REGISTER_ROUTE", handler -> {
      JsonObject message = (JsonObject) handler.body();
      HttpMethod method = HttpMethod.valueOf(message.getString("method"));
      router.route(method, message.getString("url"))
        .order(1)
        .handler(cxt -> cxt.json(new JsonObject().put("message", "This works..!!")));
    });

And this event is triggered from another verticle like this

vertx.eventBus().send("REGISTER_ROUTE",
        new JsonObject()
          .put("url", "/test-route")
          .put("method", "GET")
      );

Issue is that on windows machine this almost always works. But on a testing linux instance on AWS

  • I generally receive a 404 Not Found response instead of the actual response
  • Or I get 2 success response(200) and one 404
  • Or I get Two 404 and 1 success response

Last two of the scenarios not very sure what's the correlation to number 3(since this success/error response seems to refresh on a cycle of 3 subsequent requests). Thought it could be to number of instances of the server verticle. But modifying the instance count doesn't change this behavior either.

I have a custom error handler for 404 registered like below

router.errorHandler(404, routingContext -> {
      LOGGER.info("HTTP-404 Error Handler invoked");
      LOGGER.info("Router :" + router.toString() + " Routes Size: " + router.getRoutes().size());
      JsonObject error = new JsonObject()
        .put("error", "Resource not found");
      routingContext.response()
        .setStatusCode(404)
        .putHeader(HttpHeaders.CONTENT_TYPE, "application/json")
        .end(error.toBuffer());
    });

Whenever a 404 response is received I could see from the logs that router states does show there is a route declared with the given PATH and HTTP method combination.

I have tried registering route using the HTTP method specific syntax like router.get(url), that didn't seem to make any difference either.

Vert.x Version: 4.2.7

JDK: Eclipse Temurin 11.0.14.1+1

OS: Centos 7 on EC2

Problem is that issue doesn't occur always so it's becoming more and more difficult to identify the root cause and fix it.

Please let me know if there is anything that is wrong/missing in this. Also I have created a sample project here. This is a close replica of what I have on my actual project. Note: The issue didn't generally occur to me on Windows (for whatever reasons).

2

There are 2 answers

4
tsegismont On BEST ANSWER

In App class, 4 instances of each verticle are deployed.

vertx.deployVerticle(Server.class.getName(), new DeploymentOptions().setInstances(4))
      .compose(server -> {
        return vertx.deployVerticle(RouteRegistration.class.getName(), new DeploymentOptions().setInstances(4))
          .onSuccess(id -> LOGGER.info("Application started Successfully"))
          .onFailure(LOGGER::catching);
      });vertx.deployVerticle(Server.class.getName(), new DeploymentOptions().setInstances(4))
      .compose(server -> {
        return vertx.deployVerticle(RouteRegistration.class.getName(), new DeploymentOptions().setInstances(4))
          .onSuccess(id -> LOGGER.info("Application started Successfully"))
          .onFailure(LOGGER::catching);
      });

This means that:

  • a shared HTTP server will be created and incoming connections load-balanced between instances of the Server verticle.
  • messages sent from RouteRegistration verticle instances will be load-balanced between consumers (eventBus.send is point-to-point).

Consequently, connections will be handled by different routers with different setups.

On your local machine, I don't know why it works, perhaps you deploy a single instance?

Anyway, to fix the issue, you must have the same router configuration in every router instance, so the RouteRegistration must publish the message so that every consumer instance gets it:

vertx.eventBus().publish("REGISTER_ROUTE",
      new JsonObject()
        .put("url", "/test-route")
        .put("method", "GET")
    );
1
TungJa On

I had the same problem, and switched back to deploy (Supplier splv ,DeploymentOptions opt ) , and it worked 100% . example : vertx.deployVerticle(()->{ new VerticleFirst(router,...); }, deployOptions );