Vert.x Event Bus
Event bus messaging — point-to-point, pub/sub, request-reply, codecs, clustering.
# CLAUDE.md — Vert.x Event Bus
## What it is
- An in-process (and optionally cluster-wide) message bus baked into Vert.x.
- Decouples senders from receivers — verticles communicate by **address** (a string), not by Java references.
- Works in three modes:
- **Point-to-point** — one consumer receives.
- **Pub/Sub** — all consumers receive.
- **Request/Reply** — sender gets a response.
## Sending messages
```java
EventBus eb = vertx.eventBus();
// Point-to-point
eb.send("orders.create", new JsonObject().put("userId", "123"));
// Pub/Sub
eb.publish("user.created", new JsonObject().put("id", "123"));
// Request/Reply
eb.request("orders.find", "order-123").onSuccess(reply -> {
log.info("got order: {}", reply.body());
});
```
- Addresses are simple strings. Use a hierarchical convention: `orders.create`, `orders.cancel`, `users.update`.
- Don't put PII or large payloads in event-bus messages — they're broadcast across the cluster.
## Consuming
```java
eb.consumer("orders.create", message -> {
JsonObject body = (JsonObject) message.body();
OrderId id = createOrder(body);
message.reply(new JsonObject().put("id", id.toString()));
});
```
- Always reply on a request — if you don't, the sender gets a timeout.
- Use `message.fail(code, msg)` to signal an error to the sender.
- Unsubscribe via the `MessageConsumer` returned by `consumer(...)` when shutting down.
## Codecs
- Default codecs: `String`, `JsonObject`, `JsonArray`, `Buffer`, primitive boxed types.
- For custom POJOs, register a codec:
```java
eb.registerDefaultCodec(MyDto.class, new MyDtoCodec());
```
- For cluster mode, all nodes must register the same codecs. Otherwise messages won't deserialize.
## Clustering
- Vert.x can cluster across nodes via Hazelcast, Infinispan, Ignite, or ZooKeeper.
- The same `EventBus` API works locally and in cluster mode.
- For cluster mode: `Vertx.clusteredVertx(options, ar -> ...)`.
- Network split-brain handling: configure the underlying clustering layer carefully. Defaults are not production-ready.
## Patterns
- **Service-locator alternative**: register handlers as services on the bus instead of injecting them.
- **Saga orchestration**: each step publishes an event; coordinator listens and dispatches the next step.
- **Cache invalidation**: publish on `cache.invalidate.{key}`; every node consumes and updates its local cache.
## Performance
- In-process: ~1–10 µs per message.
- Clustered: depends on the cluster manager. Hazelcast adds ~1 ms per hop.
- For high throughput, batch messages or use direct verticle calls instead of the event bus.
## Service proxies
- Vert.x can generate type-safe proxies for an interface — calls become event-bus messages under the hood:
```java
@ProxyGen
public interface UserService {
void findById(String id, Handler<AsyncResult<JsonObject>> handler);
}
```
- Generated code (annotation processor) creates the proxy and the codec.
- Useful for cross-language clients in clustered setups.
## Don't
- Don't use the event bus for high-throughput hot paths between two verticles in the same JVM. Direct method calls are faster.
- Don't broadcast sensitive data on a clustered bus without encryption (`SSLContext` on the cluster manager).
- Don't forget to reply on `request` consumers. Senders will time out.
- Don't use mutable shared objects as message bodies. Use immutable JSON or POJOs with codecs.
Other Java templates
Modern Java Rules
Java 21+ defaults: records, sealed types, pattern matching, virtual threads, var.
Java Testing with JUnit 5
JUnit 5 + AssertJ + Mockito + Testcontainers — opinionated test conventions.
Java Virtual Threads & Concurrency
Project Loom virtual threads, structured concurrency, and modern concurrent patterns.
Java Build (Maven & Gradle)
Build conventions, dependency management, multi-module projects, and CI patterns.
Java Streams & Collections
Streams API, immutable collections, Collectors, and idiomatic data manipulation.