The Vert.x framework facilitates high-performance asynchronous programming. When a request arrives, it is delegated to the event loop rather than blocking threads. The server dispatches the task and continues processing immediately. Once the background operation completes, the result is returned via a callback mechanism, notifying the client. This pattern represents an asynchronous response flow initiated from the backend.
Most applications consist primarily of a single Vert.x instance. By extending AbstractVerticle, developers gain access to the injected vertx component within the lifecycle methods.
Project Configuration
Initialize a Maven-based project structure. Add the necessary core and web dependencies to your pom.xml.
<!-- Core Runtime -->
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-core</artifactId>
<version>4.5.1</version>
</dependency>
<!-- Web Server Module -->
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-web</artifactId>
<version>4.5.1</version>
</dependency>
Route Handler Implementation
Create a class named RequestDispatcher that extends AbstractVerticle. This component manages HTTP routes and forwards logic to other services via the Event Bus.
package com.dev.vertx.demo;
import io.vertx.core.AbstractVerticle;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpServerOptions;
import io.vertx.ext.web.Router;
public class RequestDispatcher extends AbstractVerticle {
@Override
public void start() {
Router router = Router.router(vertx);
System.out.println("Router initialization complete");
// Scheduled task executed every second
vertx.setPeriodic(1000L, id -> {
System.out.println("Timer triggered: " + id);
});
// Handle request for endpoint A
router.route("/api/processA").handler(ctx -> {
vertx.eventBus().<String> send(
ProcessService.ADDRESS_A,
"Data Payload A",
ar -> {
if (ar.succeeded()) {
System.out.println(ar.result().body());
}
System.out.println("Handler A finished");
ctx.response().end();
}
);
});
// Handle request for endpoint B
router.route("/api/processB").handler(ctx -> {
vertx.eventBus().<String> send(
ProcessService.ADDRESS_B,
"Data Payload B",
ar -> {
if (ar.succeeded()) {
System.out.println(ar.result().body());
}
System.out.println("Handler B finished");
ctx.response().end();
}
);
});
// Handle request for endpoint C
router.route("/api/processC").handler(ctx -> {
vertx.eventBus().<String> send(
AsyncExecutor.ADDRESS_C,
"Data Payload C",
ar -> {
if (ar.succeeded()) {
System.out.println(ar.result().body());
}
System.out.println("Handler C finished");
ctx.response().end();
}
);
});
// Start the HTTP listener on port 8080
vertx.createHttpServer(new HttpServerOptions()).requestHandler(router::accept).listen(8080);
}
}
Service Handlers
Services listening on the Event Bus must also extend AbstractVerticle. They consume messages, perform tasks, and reply with results.
ProcessService.java
package com.dev.vertx.demo;
import io.vertx.core.AbstractVerticle;
public class ProcessService extends AbstractVerticle {
public static final String ADDRESS_A = "APP.SERVICE.DISPATCH.A";
public static final String ADDRESS_B = "APP.SERVICE.DISPATCH.B";
@Override
public void start() {
// Consumer for Address A
vertx.eventBus().consumer(ADDRESS_A, msg -> {
System.out.println("Received: " + msg.body());
System.out.print("Service A processing");
msg.reply("Result_A_Success");
});
// Consumer for Address B
vertx.eventBus().consumer(ADDRESS_B, msg -> {
System.out.println("Received: " + msg.body());
System.out.print("Service B processing");
msg.reply("Result_B_Success");
});
}
}
AsyncExecutor.java
package com.dev.vertx.demo;
import io.vertx.core.AbstractVerticle;
public class AsyncExecutor extends AbstractVerticle {
public static final String ADDRESS_C = "APP.SERVICE.EXECUTOR.C";
@Override
public void start() {
vertx.eventBus().consumer(ADDRESS_C, msg -> {
System.out.println("Payload received: " + msg.body());
System.out.print("Executor C handling");
msg.reply("Result_C_Success");
});
}
}
Application Deployment
Use a main entry point to deploy the various verticles to the cluster or local instance.
package com.dev.vertx.demo;
import io.vertx.core.Vertx;
public class SystemBoot {
public static void main(String[] args) {
Vertx vertxInstance = Vertx.vertx();
// Deploy service workers first
vertxInstance.deployVerticle(new ProcessService());
vertxInstance.deployVerticle(new AsyncExecutor());
// Deploy the web handler last
vertxInstance.deployVerticle(new RequestDispatcher());
}
}
Execution Verification
Initiate requests against the endpoints using a browser or HTTP client:
- http://localhost:8080/api/processA
- http://localhost:8080/api/processB
- http://localhost:8080/api/processC
Sample console output upon execution:
Router initialization complete
Received: Data Payload A
Service A processingResult_A_Success
Handler A finished
Timer triggered: 1000
Timer triggered: 1001
Received: Data Payload B
Service B processingResult_B_Success
Handler B finished
Timer triggered: 1002
Timer triggered: 1003
Received: Data Payload C
Executor C handlingResult_C_Success
Handler C finished
Timer triggered: 1004
Timer triggered: 1005
This sequence demonstrates how requests traverse the event bus, are processed asynchronously by independent verticles, and return data without blocking the main thread.