How to Call the Next Handler in Vert.x
We quickly go over how to use Java and Vert.x to limit the amount of traffic handled by our application.
Join the DZone community and get the full member experience.
Join For FreeIn Vert.x, when a Router
takes an HTTP request, it finds a matching route (if any) and then it calls the handler of the route passing in an instance of RoutingContext
. More than one handler can be bounded to a route. This means that you can tell the router to route this context to the next matching route without ending the response in your handler.
Let's assume we want to control and limit the amount of incoming and outgoing network traffic. For example, let’s say we provide a service that is configured to allow 10 requests/second. Similarly, let's assume we use a circuit breaker for fault detection related to the service that the incoming request wants to access. In this case, if the incoming requests exceed the defined limit, or the service is unavailable, it will be necessary to refuse the request.
Calling the next handler offers us a useful way to manage the kind of need that's requiring different controls for the same purpose.
Calling the Next Handler
@Override
public void start(Future<Void> future) {
final ConfigStoreOptions rateOptions = new ConfigStoreOptions()
.setType("file")
.setOptional(true)
.setConfig(new JsonObject().put("path", System.getProperty("user.dir") + "/src/main/resources/config.json"));
final ConfigRetrieverOptions options = new ConfigRetrieverOptions().addStore(rateOptions);
final Router router = RouterHelper.createRouter(vertx, "Hello from rate limiter example!");
router.get("/limiting").handler(new CircuitBreakerHandler(options));
router.get("/limiting").handler(new RateLimiterHandler(options));
HttpServerHelper.createAnHttpServer(vertx, router, config(), future);
}
In the above code, we created two routes for the same path and bounded different handlers. When a GET /limiting request arrives the CircuitBreakerHandler
will work first.
@Override
public void handle(RoutingContext context) {
final ConfigRetriever retriever = ConfigRetriever.create(context.vertx(), options);
retriever.getConfig(ar -> {
if (ar.failed()) {
log.error("Failed to retrieve the configuration");
} else {
final JsonObject config = ar.result();
final boolean circuitBreaker = config.getBoolean("circuitbreaker");
if (!circuitBreaker) {
context.next();
} else {
context.response()
.putHeader(CONTENT_TYPE, HTML_PRODUCE)
.setStatusCode(HTTP_SERVICE_UNAVAILABLE)
.end("Service unavailable!");
}
}
});
}
In the handler, we are checking firstly to CircuitBreaker and if it's closed we call next method of the RoutingContext. The next method tell the router to route this context to the next matching route (if any). In our example, this will provide calling RateLimiterHandler. I created a repository for this example, you can examine.
Conclusion
Vert.x allows multiple handlers binding to a route. This provides routing the handled context to the next matching route and so encapsulates your handlers for different logic by linking together such as a chain.
References
Opinions expressed by DZone contributors are their own.
Comments