DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • High-Performance Reactive REST API and Reactive DB Connection Using Java Spring Boot WebFlux R2DBC Example
  • Unlocking the Power of Oracle NoSQL With Quarkus: Seamless Integration for Cloud-Age Applications
  • Demystifying Virtual Thread Performance: Unveiling the Truth Beyond the Buzz
  • Spring Boot, Quarkus, or Micronaut?

Trending

  • A Simple, Convenience Package for the Azure Cosmos DB Go SDK
  • The Role of Functional Programming in Modern Software Development
  • Teradata Performance and Skew Prevention Tips
  • Microsoft Azure Synapse Analytics: Scaling Hurdles and Limitations
  1. DZone
  2. Coding
  3. Frameworks
  4. The Magic of Quarkus With Vert.x in Reactive Programming

The Magic of Quarkus With Vert.x in Reactive Programming

Explore reactive programming in Quarkus, along with detailed insights and practical examples in Java to illustrate its transformative capabilities.

By 
Reza Ganji user avatar
Reza Ganji
DZone Core CORE ·
Jun. 03, 24 · Tutorial
Likes (3)
Comment
Save
Tweet
Share
6.8K Views

Join the DZone community and get the full member experience.

Join For Free

Reactive programming has significantly altered how developers tackle modern application development, particularly in environments that demand top-notch performance and scalability. Quarkus, a Kubernetes-native Java framework specifically optimized for GraalVM and HotSpot, fully embraces the principles of reactive programming to craft applications that are responsive, resilient, and elastic. This article comprehensively explores the impact and effectiveness of reactive programming in Quarkus, providing detailed insights and practical examples in Java to illustrate its transformative capabilities.

What Is Reactive Programming?

Reactive programming is a programming paradigm that focuses on handling asynchronous data streams and the propagation of change. It provides developers with the ability to write code that responds to changes in real time, such as user inputs, data updates, or messages from other services. This approach is particularly well-suited for building applications that require real-time responsiveness and the ability to process continuous streams of data. By leveraging reactive programming, developers can create more interactive and responsive applications that can adapt to changing conditions and events.

Key features of reactive programming include:

  • Asynchronous: Non-blocking operations that allow multiple tasks to run concurrently
  • Event-driven: Actions are triggered by events such as user actions or data changes
  • Resilient: Systems remain responsive under load by handling failures gracefully
  • Scalable: Efficient resource usage to handle a high number of requests

Why Quarkus for Reactive Programming?

Quarkus, a framework designed to harness the advantages of reactive programming, aims to provide a streamlined and efficient environment for developing reactive applications. There are several compelling reasons to consider Quarkus for such applications:

  • Native support for Reactive frameworks: Quarkus seamlessly integrates with popular reactive libraries such as Vert.x, Mutiny, and Reactive Streams. This native support allows developers to leverage the full power of these frameworks within the Quarkus environment.
  • Efficient resource usage: Quarkus's native image generation and efficient runtime result in lower memory consumption and faster startup times. This means that applications built with Quarkus can be more resource-efficient, leading to potential cost savings and improved performance.
  • Developer productivity: Quarkus offers features like live coding, significantly improving the development experience. This means developers can iterate more quickly, leading to faster development cycles and ultimately more productive software development.

Getting Started With Reactive Programming in Quarkus

Let’s dive into a simple example to demonstrate reactive programming in Quarkus using Java. We’ll create a basic REST API that fetches data asynchronously.

Step 1: Setting Up the Project

First, create a new Quarkus project:

Shell
 
mvn io.quarkus:quarkus-maven-plugin:create \
    -DprojectGroupId=com.example \
    -DprojectArtifactId=reactive-quarkus \
    -DclassName="com.example.GreetingResource" \
    -Dpath="/greeting"
cd reactive-quarkus


Add the necessary dependencies in your pom.xml:

XML
 
<dependencies>
    <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-resteasy-reactive</artifactId>
    </dependency>
    <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-smallrye-mutiny</artifactId>
    </dependency>
    <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-vertx</artifactId>
    </dependency>
</dependencies>


Step 2: Start Coding

Now, create a simple REST endpoint using Mutiny, a reactive programming library designed for simplicity and performance:

Java
 
import io.smallrye.mutiny.Uni;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/greeting")
public class GreetingResource {

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Uni<Greeting> greeting() {
        return Uni.createFrom().item(() -> new Greeting("Hello, Reactive World!"))
                  .onItem().delayIt().byMillis(1000); // Simulate delay
    }

    public static class Greeting {
        public String message;

        public Greeting(String message) {
            this.message = message;
        }
    }
}


In this example:

  • We define a REST endpoint /greeting that produces JSON.
  • The greeting method returns a Uni<Greeting> which represents a single value or failure, a concept from Mutiny.
  • We simulate a delay using onItem().delayIt().byMillis(1000) to mimic an asynchronous operation

Step 3: Running the Application

To run the application, use the Quarkus development mode:

Shell
 
./mvnw quarkus:dev


Now, visit http://localhost:8080/greeting to see the response:

JSON
 
{
  "message": "Hello, Reactive World!"
}


Unit Testing Reactive Endpoints

When testing reactive endpoints in Quarkus, it's important to verify that the application functions correctly in response to various conditions. Quarkus facilitates seamless integration with JUnit 5, allowing developers to effectively write and execute unit tests to ensure the proper functionality of their applications.

Step 1: Adding Test Dependencies

Ensure you have the following dependencies in your pom.xml for testing:

XML
 
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-junit5</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>io.rest-assured</groupId>
    <artifactId>rest-assured</artifactId>
    <scope>test</scope>
</dependency>


Step 2: Writing a Unit Test

Create a test class to verify the behavior of the GreetingResource:

Java
 

import io.quarkus.test.junit.QuarkusTest;
import io.rest-assured.RestAssured;
import org.junit.jupiter.api.Test;

import static org.hamcrest.CoreMatchers.is;

@QuarkusTest
public class GreetingResourceTest {

    @Test
    public void testGreetingEndpoint() {
        RestAssured.when().get("/greeting")
                   .then()
                   .statusCode(200)
                   .body("message", is("Hello, Reactive World!"));
    }
}


In this test:

  • We use the @QuarkusTest annotation to enable Quarkus testing features.
  • We use RestAssured to send an HTTP GET request to the /greeting endpoint and verify the response status code and body.

Step 3: Running the Tests

To run the tests, use the Maven test command:

Shell
 
./mvnw test


The test will execute and verify that the /greeting endpoint returns the expected response.

Advanced Usage: Integrating With Databases

Let’s extend the example by integrating a reactive database client. We’ll use the reactive PostgreSQL client provided by Vert.x.

Add the dependency for the reactive PostgreSQL client:

XML
 
<dependency>
    <groupId>io.quarkiverse.reactive</groupId>
    <artifactId>quarkus-reactive-pg-client</artifactId>
</dependency>


Configure the PostgreSQL client in application.properties:

Shell
 
quarkus.datasource.db-kind=postgresql
quarkus.datasource.username=your_username
quarkus.datasource.password=your_password
quarkus.datasource.reactive.url=postgresql://localhost:5432/your_database


Create a repository class to handle database operations:

Java
 

import io.smallrye.mutiny.Uni;
import io.vertx.mutiny.pgclient.PgPool;
import io.vertx.mutiny.sqlclient.Row;
import io.vertx.mutiny.sqlclient.RowSet;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;

@ApplicationScoped
public class GreetingRepository {

    @Inject
    PgPool client;

    public Uni<String> findGreeting() {
        return client.query("SELECT message FROM greetings WHERE id = 1")
                     .execute()
                     .onItem().transform(RowSet::iterator)
                     .onItem().transform(iterator -> iterator.hasNext() ? iterator.next().getString("message") : "Hello, default!");
    }
}


Update the GreetingResource to use the repository:

Java
 

import io.smallrye.mutiny.Uni;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/greeting")
public class GreetingResource {

    @Inject
    GreetingRepository repository;

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Uni<Greeting> greeting() {
        return repository.findGreeting()
                         .onItem().transform(Greeting::new);
    }

    public static class Greeting {
        public String message;

        public Greeting(String message) {
            this.message = message;
        }
    }
}


This setup demonstrates how to perform asynchronous database operations using the reactive PostgreSQL client. The findGreeting method queries the database and returns a Uni<String> representing the greeting message.

Handling Errors in Reactive Programming

Handling errors gracefully is a critical aspect of building resilient reactive applications. Mutiny provides several operators to handle errors effectively.

Update the GreetingRepository to include error handling:

Java
 
public Uni<String> findGreeting() {
    return client.query("SELECT message FROM greetings WHERE id = 1")
                 .execute()
                 .onItem().transform(RowSet::iterator)
                 .onItem().transform(iterator -> iterator.hasNext() ? iterator.next().getString("message") : "Hello, default!")
                 .onFailure().recoverWithItem("Hello, fallback!");
}


In this updated method:

  • We use onFailure().recoverWithItem("Hello, fallback!") to provide a fallback message in case of any failure during the database query.

Reactive Event Bus With Vert.x

Quarkus seamlessly integrates with Vert.x, a powerful reactive toolkit, to provide a high-performance event bus for developing sophisticated event-driven applications. This event bus allows various components of your application to communicate asynchronously, facilitating efficient and scalable interaction between different parts of the system. 

Add the necessary Vert.x dependencies:

XML
 
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-vertx</artifactId>
</dependency>


Create a Vert.x consumer to handle events:

Java
 

import io.quarkus.vertx.ConsumeEvent;
import io.smallrye.mutiny.Uni;
import javax.enterprise.context.ApplicationScoped;

@ApplicationScoped
public class GreetingService {

    @ConsumeEvent("greeting")
    public Uni<String> generateGreeting(String name) {
        return Uni.createFrom().item(() -> "Hello, " + name + "!")
                  .onItem().delayIt().byMillis(500); // Simulate delay
    }
}


Now, Update the GreetingResource to send events to the event bus:

Java
 

import io.smallrye.mutiny.Uni;
import io.vertx.mutiny.core.eventbus.EventBus;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;

@Path("/greeting")
public class GreetingResource {

    @Inject
    EventBus eventBus;

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Uni<Greeting> greeting(@QueryParam("name") String name) {
        return eventBus.<String>request("greeting", name)
                       .onItem().transform(reply -> new Greeting(reply.body()));
    }

    public static class Greeting {
        public String message;

        public Greeting(String message) {
            this.message = message;
        }
    }
}


In this example:

  • We define an event consumer GreetingService that listens for greeting events and generates a greeting message.
  • The GreetingResource sends a greeting event to the event bus and waits for the response asynchronously.

Comparison: Quarkus vs. Spring in Reactive Capabilities

When building reactive applications, Quarkus and Spring offer robust frameworks, each with unique approaches and strengths.

1. Framework Integration

Spring

Spring Boot leverages Spring WebFlux for reactive programming and seamlessly integrates with the Spring ecosystem, supporting Project Reactor as its reactive library. 

Quarkus

Quarkus utilizes Vert.x and Mutiny for reactive programming, providing native support from the ground up and optimizing for performance and efficiency.

2. Performance and Resource Efficiency

Spring

While Spring Boot with WebFlux offers good performance for reactive applications, it may be heavier in terms of resource usage compared to Quarkus.

Quarkus

Quarkus is designed to be lightweight and fast, showcasing lower memory consumption and faster startup times, especially when compiled to a native image with GraalVM.

3. Developer Experience

Spring

Spring Boot offers a mature ecosystem with extensive documentation and strong community support, making it easy for developers familiar with Spring to adopt reactive programming.

Quarkus

Quarkus provides an excellent developer experience with features like live coding and quick feedback loops. Its integration with reactive libraries like Mutiny makes it intuitive for developers new to reactive programming.

4. Cloud-Native and Microservices

Spring

Widely used for building microservices and cloud-native applications, Spring Boot provides a rich set of tools and integrations for deploying applications to the cloud.

Quarkus

Designed with cloud-native and microservices architectures in mind, Quarkus showcases efficient resource usage and strong support for Kubernetes, making it a compelling choice for cloud deployments.

5. Ecosystem and Community

Spring

Boasting a vast ecosystem with numerous extensions and integrations, Spring is supported by a large community of developers.

Quarkus

Rapidly gaining popularity, Quarkus offers a comprehensive set of extensions, and its community is also expanding, contributing to its ecosystem.

Conclusion

Reactive programming in Quarkus provides a cutting-edge approach to enhancing the performance and scalability of Java applications. By harnessing the capabilities of reactive streams and asynchronous operations, Quarkus empowers developers to build applications that are not only robust and high-performing, but also well-suited for modern cloud-native environments. The efficiency and power of Quarkus, combined with its rich ecosystem of reactive libraries, offer developers the tools they need to handle a wide range of tasks, from simple asynchronous operations to complex data streams, making Quarkus a formidable platform for reactive programming in Java. 

Quarkus Reactive programming Vert.x Java (programming language) Spring Boot

Opinions expressed by DZone contributors are their own.

Related

  • High-Performance Reactive REST API and Reactive DB Connection Using Java Spring Boot WebFlux R2DBC Example
  • Unlocking the Power of Oracle NoSQL With Quarkus: Seamless Integration for Cloud-Age Applications
  • Demystifying Virtual Thread Performance: Unveiling the Truth Beyond the Buzz
  • Spring Boot, Quarkus, or Micronaut?

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!