vert.xvertx-verticlevertx-eventbus

Vertx - This Route is exclusive for already mounted sub router issue


I am trying to create 2 Verticles one for the http server and another for my sockjs eventbus bridge. Then I am trying to deplowy the two Verticles in the Main app. For for some reason I get this error in my Sockjs Verticle.

java.lang.IllegalStateException: This Route is exclusive for already mounted sub router.

 
Router router = Router.router(vertx);

vertx.deployVerticle(new RestApiVerticle(router))
        .onFailure(startPromise::fail)
        .onSuccess(id -> {
                            LOG.info("Deployed {} with id {}", RestApiVerticle.class.getSimpleName(), id);
                            startPromise.complete();
                          });
       
        vertx.deployVerticle(new com.ali.websockjs.WebSocketVerticle(router))
                .onFailure(startPromise::fail)
                .onSuccess(id -> {
                    LOG.info("Deployed {} with id {}", com.ali.websockjs.WebSocketVerticle.class.getSimpleName(), id);
                    startPromise.complete();
                  });

In my RestApiVerticle

private Router router;
   
    public RestApiVerticle(Router router) {
       
        this.router = router;
       
    }

router.route().handler(bodyHandler).failureHandler(FailureResponse.handleFailure());
       
        router.route("/").handler(req -> req.response().end("Hello there!"))
                .failureHandler(error -> LOG.error("Something is wrong with server!!"));

and in my WebSocketVerticle, where I get error

private Router router;

    public WebSocketVerticle(Router router) {
        this.router = router;
    }

Below code I get error
// mount the bridge on the router
        router.mountSubRouter("/eventbus", subRouter).failureHandler(error -> LOG.error("error {}", error));

Please help!!!!!!

UPDATE

Doing your approach is giving my CORS error in the browser

Access to XMLHttpRequest at 'http://localhost:1234/eventbus/info?t=1653982669356' from origin 'http://localhost:4200' has been blocked by CORS policy:

vertx.deployVerticle(new RestApiVerticle(router))
          .compose(var ->
            vertx.deployVerticle(new WebSocketVerticle(router)))
          .onFailure(startPromise::fail)
          .onSuccess(server -> {
                LOG.debug("Server and Sockjs started !!");
                startPromise.complete();
              });

any suggestion??


Solution

  • The error is telling you that there is a configuration problem with your setup. In a way this is what is happening:

    You have a router and in this router you have a route /eventbus that transfers the route evaluation from the 1st router to the 2nd (the sockjs router).

    It seems that your code is trying to call that setup twice. This means that there's something wrong. The problem is that on that given route, if you transfer the execution to the 2nd router, the 3rd one (causing the problem) will never be called because the processing is now happening on the 2nd router.

    I'd say that probably you need to debug your application startup and see why is the setup being called more than once.

    My assumption here is that the problem you're seeing is coming from a race condition on your deployment. You're calling:

    vertx.deployVerticle(new RestApiVerticle(router))
    vertx.deployVerticle(new WebSocketVerticle(router))
    

    These are asynchronous operations, and they will race to add their handlers to the shared router, now it could be that the WebSocketVerticle runs first and adds the eventbus handler, and then the RestApiVerticle runs and tries to add more handlers and this is problematic (like described above).

    I believe the solution is to use composition to ensure your handlers are added in the right order:

    vertx.deployVerticle(new RestApiVerticle(router))
      .compose(1stDeploymentId ->
        vertx.deployVerticle(new WebSocketVerticle(router)))
      .onSuccess(2ndDeploymentId -> startPromise.complete();
      .onFailure(startPromise::fail);
    

    You may want to re-arrange the composition if you need to log the deployment ids.