Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Verticles and uncaught exceptions

Tags:

vert.x

Considering the scenario that one of the verticles throws an uncaught exception.

What happens next? If the verticle state is removed from the system is there some mechanism similar to erlang supervisors to restart the verticle?

Documentation is not very clear about this aspect.

Update based on comments: What interest me the most is the situation when an exception is thrown from the processing handlers of a received message (through the bus)

Regards

like image 612
mhstnsc Avatar asked Jun 22 '15 15:06

mhstnsc


4 Answers

I have answered part of my own question (with the help of a test program)

When exception is thrown in a event handler then the exception is caught by vert.x and swallowed (ignored). The event handler will process the next message.

Update: The app can register an exception handler and have all the uncaught Throwable delivered to this handler. There you can perform additional general processing

Update2: Use Vertx.exceptionHandler to register the handler

like image 181
mhstnsc Avatar answered Sep 30 '22 01:09

mhstnsc


To add a bit to the previous answer, if you want to react to all uncaught exceptions, register handler on vertx object, as follows:

vertx.exceptionHandler(new Handler<Throwable>() {       
    @Override
    public void handle(Throwable event) {
        // do what you meant to do on uncaught exception, e.g.:
        System.err.println("Error");
        someLogger.error(event + " throws exception: " + event.getStackTrace());
    }
});
like image 23
ph0enix Avatar answered Sep 30 '22 01:09

ph0enix


Vert.x is all about the same style, asynchronous programming, which is mainly highlighted by callback handlers.

To handle the deployment failure case, you have first to go the programmatic way, i.e. you have to deploy your verticle programmatically through let's say a deployment verticle providing a completion handler that will be populated with deployment result, here down a sample using Java (since your haven't opt for a specific language, I will go with my best) where:

  • MainVerticle: is your deployment verticle (used mainly to deploy other verticles)
  • some.package.MyVerticle: is your real verticle, note that I used the id here and not an instance.
public class MainVerticle extends AbstractVerticle {  
  public void start() {
    vertx.deployVerticle("some.package.MyVerticle", res -> {
      if (res.succeeded()) {
        // Do whatever if deployment succeeded
      } else {
        // Handle deployment failure here...
      }
    });
  }
}

Now when it comes to 'messaging failures', it would be harder to highlight a specific case since it can occur at many places and on behalf of both messaging ends.

If you want to register a failure case handler when sending a message, you can instantiate a MessageProducer<T> representing the stream it can be written to, then register an exception handler on it:

EventBus eb = vertx.eventBus();
MessageProducer<String> sender = eb.sender("someAddress");
sender.exceptionHandler(e -> { 
  System.out.println("An error occured" + e.getCause()); 
});
sender.write("Hello...");

On the other side, you can handle failure case when reading the received messages pretty much the same way, but using a MessageConsumer<T> this time:

EventBus eb = vertx.eventBus();
MessageConsumer<String> receiver = eb.consumer("someAddress");
receiver.exceptionHandler(e -> { 
  System.out.println("An error occured while readeing data" + e.getCause()); 
}).handler(msg -> {
  System.out.println("A message has been received: " + msg.body());
});
like image 24
tmarwen Avatar answered Oct 02 '22 01:10

tmarwen


I ran into something similar to this. When an exception happens as part of processing a message in a Verticle, I just wanted to reply with the Exception.

The idea is to just bubble up the exceptions all the way back to the entry point in the app where a decision can be made about what to do with the failure, while capturing the entire stack along the way.

To accomplish it I wrote this function:

protected ReplyException buildReplyException(Throwable cause, String message)
    {
        ReplyException ex = new ReplyException(ReplyFailure.RECIPIENT_FAILURE, -1, message);
        ex.initCause(cause);
        return ex;
    }

Which I then use to build handlers, or reply handlers, like this:

reply -> {
    if (reply.succeeded()) {
        message.reply(true);
    } else {
        message.reply(buildReplyException(reply.cause(), ""));
    }
});

This way the guy that sent the original message will get a failed response which contains a cause that's an exception which has a full stack trace populated on it.

This approach worked very well for me to handle errors while processing messages.

like image 44
Juan Bustamante Avatar answered Oct 03 '22 01:10

Juan Bustamante