Episode ini membahas reactive programming di Quarkus: reactive stack dengan Vert.x, konsep Uni dan Multi untuk pemrosesan asynchronous, reactive messaging dengan Kafka, AMQP, atau MQTT, serta kapan menggunakan reactive dibandingkan imperative.

Aplikasi modern harus melayani ribuan request bersamaan. Model blocking tradisional menahan satu thread untuk satu request — boros dan tidak scalable. Reactive programming menawarkan alternatif: satu thread melayani banyak operasi secara non-blocking.
Episode 15 membahas reactive stack Quarkus yang dibangun di atas Vert.x, konsep Uni dan Multi untuk pemrosesan asynchronous, reactive messaging dengan Kafka, AMQP, atau MQTT, serta panduan kapan memakai reactive dibandingkan imperative.
Vert.x adalah toolkit event-driven yang menjadi fondasi non-blocking Quarkus. RESTEasy Reactive, reactive routes, dan event loop semuanya berjalan di atas Vert.x. Model utamanya: event loop yang memproses event secara non-blocking dan worker thread untuk pekerjaan blocking.
Setiap aplikasi Quarkus secara default memiliki beberapa event loop. Permintaan REST diproses di event loop; pekerjaan blocking (seperti JDBC sinkron) dilimpahkan ke worker.
Selain JAX-RS, Quarkus menawarkan reactive routes berbasis Vert.x: annotate method dengan @Route(path = "/api/status", methods = HttpMethod.GET) dan terima RoutingContext untuk menulis response langsung. Untuk API JSON sederhana, RESTEasy Reactive (episode 5) lebih nyaman; reactive routes berguna untuk kontrol tingkat rendah.
Uni mewakili satu hasil (atau satu kegagalan) di masa depan. Ini padanan reaktif dari CompletableFuture:
import io.smallrye.mutiny.Uni;
import jakarta.enterprise.context.ApplicationScoped;
@ApplicationScoped
public class QuoteService {
public Uni<String> ambilQuote() {
return Uni.createFrom().item("Halo, dunia reactive!")
.onItem().delayIt().by(java.time.Duration.ofMillis(100));
}
}Uni.createFrom().item("...") membuat Uni langsung sukses. Rangkaian .onItem() dan .delayIt() membangun pipeline transformasi tanpa memblokir thread.
Multi mewakili aliran (stream) beberapa item. Cocok untuk data streaming atau event:
import io.smallrye.mutiny.Multi;
import java.time.Duration;
public Multi<Integer> hitung() {
return Multi.createFrom()
.range(1, 10)
.onItem().transform(n -> n * n);
}Multi.createFrom().range(1, 10) memancarkan 1 sampai 9, lalu .transform(n -> n * n) mengubah tiap item menjadi kuadratnya. Konsumen bisa subscribe untuk menerima item satu per satu.
RESTEasy Reactive mendukung tipe Mutiny secara langsung:
import io.smallrye.mutiny.Uni;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
@Path("/api/quote")
public class QuoteResource {
@Inject
QuoteService quoteService;
@GET
public Uni<String> quote() {
return quoteService.ambilQuote();
}
}Method mengembalikan Uni<String> — request tidak memblokir thread; hasil dikirim saat Uni selesai. Ini model inti reactive REST.
SmallRye Reactive Messaging menghubungkan aplikasi dengan broker pesan secara asynchronous. Tambahkan extension:
./mvnw quarkus:add-extension -Dextensions=reactive-messaging-kafkaimport jakarta.enterprise.context.ApplicationScoped;
import org.eclipse.microprofile.reactive.messaging.Channel;
import org.eclipse.microprofile.reactive.messaging.Emitter;
import org.eclipse.microprofile.reactive.messaging.Incoming;
import io.smallrye.mutiny.Uni;
@ApplicationScoped
public class OrderMessaging {
@Channel("orders-out")
Emitter<String> ordersEmitter;
public void kirimOrder(String order) {
ordersEmitter.send(order);
}
@Incoming("orders-in")
public void prosesOrder(String order) {
System.out.println("Order diterima: " + order);
}
}@Channel("orders-out") mengirim ke channel Kafka, @Incoming("orders-in") menerima dari channel lain. Konfigurasi connector:
mp.messaging.outgoing.orders-out.connector=smallrye-kafka
mp.messaging.outgoing.orders-out.topic=orders
mp.messaging.incoming.orders-in.connector=smallrye-kafka
mp.messaging.incoming.orders-in.topic=order-events
mp.messaging.incoming.orders-in.auto.offset.reset=earliestPerintah ./mvnw quarkus:add-extension -Dextensions=reactive-messaging-kafka menambahkan Kafka connector. Untuk AMQP atau MQTT, ganti connector dengan smallrye-amqp atau smallrye-mqtt.
Kombinasi keduanya sah: pakai imperative untuk CRUD sederhana dan reactive untuk jalur I/O tinggi. Quarkus memudahkan transisi bertahap — resource reactive dan imperative bisa hidup berdampingan dalam satu aplikasi.
Episode 15 membuka dunia reactive Quarkus: memahami Vert.x sebagai fondasi non-blocking, konsep Uni untuk satu hasil dan Multi untuk aliran data, reactive messaging dengan Kafka, AMQP, dan MQTT, serta panduan kapan memakai reactive dibandingkan imperative.
Inti yang harus dibawa pulang:
Di episode 16 selanjutnya kita akan membahas native image dan startup optimization — Quarkus native image dengan GraalVM atau Mandrel, build time augmentation dan AOT compilation, optimasi startup dan memory, serta debugging native image dan tradeoff kompatibilitas.