Search code examples
restvert.xevent-bus

Vertx EventBus Reply a 'Specific' Message


We have a case as below:

enter image description here

The concern is that, the Coordinator sends out a message from a method context and gets the reponse from another:

private void forwardToVWClient(Message msg) {

        vertx.eventBus().send(RESTClient.ADDRESS, msg.body(), deliveryOptions, res -> {
            if (res.succeeded()) {
                log.info("forwardToVWClient. VW got result : success.");
                // do not reply ok until we get an OK from the Listener verticle

            } else {
                log.error("forwardToVWClient VW got result : failure.");
                msg.fail(500, res.cause().getMessage());
            }
        });
    }

then I have another event bus consuming method where I receive the response:

vertx.eventBus().consumer(ADDRESS_RESPONSE, this::handleResponseMessage);


private void handleResponseMessage(Message msg) {
        // how to reply the message received in the context of forwardToVWClient ?? 
}

So, how could I reply the message in the context of forwardToVWClient, when I receive the response in the handleResponseMessage?

Couple of ideas so far:

  1. Put the message in the vertx context ?
  2. The message object has a field : .replyAddress() that returns an int, I save that in a static ConcurrentHashMap and use it to reply a particular message. I ll post more details as an answer.

Is there a better way?


Solution

  • one way to achieve it is to save the replyAddress field of the message and use it to send a message back to the originator.

    Below is some simplified code that shows how:

    public class VehicleStateCoordinatorVerticle extends AbstractVerticle {
    
    
        final static String ADDRESS_REQUEST = "CoordinatorRequest";
        final static String ADDRESS_RESPONSE = "CoordinatorResponse";
    
        static ConcurrentHashMap<String, VWApiRequest> pendingCommands = new ConcurrentHashMap<>();
    
    
        public void start() {
            vertx.eventBus().consumer(ADDRESS_REQUEST, this::handleRequestMessage);
            vertx.eventBus().consumer(ADDRESS_RESPONSE, this::handleResponseMessage);
            log.info("===== VehicleStateCoordinatorVerticle - bus consumer ready =====");
        }
    
        private void handleRequestMessage(Message msg) {
    
                // .... omitted for brevity
                // save the replyAddress and the command for later/callback
                cmd.setReplyAddress(msg.replyAddress());
                pendingCommands.put(cmd.getVwReference(), cmd);
    
    
                forwardToVWClient(msg);
        }
    
    
        private void forwardToVWClient(Message msg) {
    
            vertx.eventBus().send(AbstractOEMClientVerticle.ADDRESS, msg.body(), deliveryOptions, res -> {
                if (res.succeeded()) {
                    log.info("forwardToVWClient. VW got result : success.");
                    // do not reply ok until we get an OK from the VWAPIServer verticle
    
                } else {
                    log.error("forwardToVWClient VW got result : failure.");
                    msg.fail(500, res.cause().getMessage());
                }
            });
        }
    
    
    
        private void handleResponseMessage(Message msg) {
    
            //..
            VWApiRequest vwApiRequest = pendingCommands.get(vwReference);
            if(vwApiRequest == null){
                log.error("No pending vwApiRequest could be found!");
                return;
            }
    
            /**
             * Instead of targeting the RESTApi address,
             * we use the replyAddress to target the specific message that is pending response.
             */
            vertx.eventBus().send(vwApiRequest.getReplyAddress(), body, deliveryOptions, res -> {
                if (res.succeeded()) {
                 // cheers!
                }
                else{
                    log.error("Error in handleResponseMessage {}", res.cause().getMessage());
                }
    
            });
        }