问题
We have a case as below:
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:
- Put the message in the vertx context ?
- 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?
回答1:
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());
}
});
}
来源:https://stackoverflow.com/questions/52605863/vertx-eventbus-reply-a-specific-message