////
This guide is maintained in the main Quarkus repository
and pull requests should be submitted there:
https://github.com/quarkusio/quarkus/tree/main/docs/src/main/asciidoc
////
= Using Eclipse Vert.x API from a Quarkus Application

include::./attributes.adoc[]

https://vertx.io[Vert.x] is a toolkit for building reactive applications.
As described in the xref:quarkus-reactive-architecture.adoc[Quarkus Reactive Architecture], Quarkus uses Vert.x underneath.

image::quarkus-reactive-core.png[Quarkus Reactive Core,width=50%, align=center]

Quarkus applications can access and use the Vert.x APIs.

This guide presents how you can build a Quarkus application using:

* the managed instance of Vert.x
* the Vert.x event bus
* the Vert.x Web Client

It's an introductory guide.
The xref:vertx-reference.adoc[Vert.x reference guide] covers more advanced features such as verticles, and native transports.

== Architecture

We are going to build a simple application exposing four HTTP endpoints:

1. `/vertx/lorem` returns the content from a small file
2. `/vertx/book` returns the content from a large file (a book)
3. `/vertx/hello` uses the Vert.x event bus to produce the response
4. `/vertx/web` uses the Vert.x Web Client to retrieve data from Wikipedia

image::quarkus-vertx-guide-architecture.png[Architecture of the Vert.x guide,width=50%, align=center]

== Solution

We recommend that you follow the instructions in the following sections and create the application step by step.
However, you can go right to the completed example.

Clone the Git repository: `git clone {quickstarts-clone-url}`, or download an {quickstarts-archive-url}[archive].

The solution is located in the `vertx-quickstart` {quickstarts-tree-url}/vertx-quickstart[directory].

[TIP]
.Mutiny
====
This guide uses the Mutiny API.
If you are not familiar with Mutiny, check xref:mutiny-primer.adoc[Mutiny - an intuitive, reactive programming library].
====


== Bootstrapping the application

Click on https://code.quarkus.io/?a=quarkus-getting-started-vertx&nc=true&e=resteasy-reactive-jackson&e=vertx[this link] to configure your application.
It selected a few extensions:

* `resteasy-reactive-jackson`, which also brings `resteasy reactive`. We are going to use it to expose our HTTP endpoints.
* `vertx`, which provides access to the underlying managed Vert.x

Click on the `Generate your application` button, download the zip file and unzip it.
Then, open the project in your favorite IDE.

If you open the generated `pom.xml` file, you can see the selected extensions:

[source, xml]
----
<dependency>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-resteasy-reactive-jackson</artifactId>
</dependency>
<dependency>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-vertx</artifactId>
</dependency>
----

While you are in the `pom.xml`, add the following dependency:

[source, xml]
----
<dependency>
  <groupId>io.smallrye.reactive</groupId>
  <artifactId>smallrye-mutiny-vertx-web-client</artifactId>
</dependency>
----

This dependency provides the Vert.x Web Client, which we will be using to implement the `/web` endpoint.


== Accessing the managed Vert.x instance

Create the `src/main/java/org/acme/VertxResource.java` file.
It will contain our HTTP endpoints.

In this file, copy the following code:

[source, java]
----
package org.acme;

import io.vertx.mutiny.core.Vertx;

import javax.inject.Inject;
import javax.ws.rs.Path;

@Path("/vertx")                        // <1>
public class VertxResource {

    private final Vertx vertx;

    @Inject                             // <2>
    public VertxResource(Vertx vertx) { // <3>
        this.vertx = vertx;             // <4>
    }
}
----
1. Declare the root HTTP path.
2. We use constructor injection to receive the managed Vert.x instance. Field injection works too.
3. Receives the Vert.x instance as a constructor parameter
4. Store the managed Vert.x instance into a field.

With this, we can start implementing the endpoints.

== Using Vert.x Core API

The injected Vert.x instance provides a set of APIs you can use.
The one we are going to use in this section is the Vert.x File System.
It provides a non-blocking API to access files.


In the `src/main/resource` directory, create a `lorem.txt` file with the following content:

[source, text]
----
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
----

Then, in the `VertxResource` file add the following method:

[source, java]
----
@GET                                                                    // <1>
@Path("/lorem")
public Uni<String> readShortFile() {                                    // <2>
    return vertx.fileSystem().readFile("lorem.txt")                     // <3>
            .onItem().transform(content -> content.toString("UTF-8"));  // <4>
}
----
1. This endpoint handles HTTP `GET` request on path `/lorem` (so the full path will be `vertx/lorem`)
2. As the Vert.x API is asynchronous, our method returns a `Uni`. The content is written into the HTTP response when the asynchronous operation represented by the Uni completes.
3. We use the Vert.x file system API to read the created file
4. Once the file is read, the content is stored in an in-memory buffer.  We transform this buffer into a String.

In a terminal, navigate to the root of the project and run:


[source, bash]
----
> ./mvnw quarkus:dev
----

In another terminal, run:

[source, bash]
----
> curl http://localhost:8080/vertx/lorem
----

You should see the content of the file printed in the console.

IMPORTANT: Quarkus provides other ways to serve static files. This is an example made for the guide.

== Using Vert.x stream capability

Reading a file and storing the content in memory works for small files, but not big ones.
In this section, we will see how you can use Vert.x streaming capability.

First, download https://www.gutenberg.org/files/2600/2600-0.txt[War and Peace] and store it in `src/main/resources/book.txt`.
It's a 3.2 Mb file, which, while not being huge, illustrates the purpose of streams.
This time, we will not accumulate the file's content in memory and write it in one batch, but read it chunk by chunk and write these chunks into the HTTP response one by one.

So, you should have the following files in your project:


[source, text]
----
.
├── mvnw
├── mvnw.cmd
├── pom.xml
├── README.md
├── src
│  └── main
│     ├── docker
│     │  ├── ...
│     ├── java
│     │  └── org
│     │     └── acme
│     │        └── VertxResource.java
│     └── resources
│        ├── application.properties
│        ├── book.txt
│        └── lorem.txt
----

Add the following method to the `VertxResource` class:

[source, java]
----
@GET
@Path("/book")
public Multi<String> readLargeFile() {                              // <1>
    return vertx.fileSystem().open("book.txt",                      // <2>
                    new OpenOptions().setRead(true)
            )
            .onItem().transformToMulti(file -> file.toMulti())       // <3>
            .onItem().transform(content -> content.toString("UTF-8") // <4>
                    + "\n------------\n");                           // <5>
}
----
1. This time, we return a Multi as we want to stream the chunks
2. We open the file using the `open` method. It returns a `Uni<AsyncFile>`
3. When the file is opened, we retrieve a `Multi` which will contain the chunks.
4. For each chunk, we produce a String
5. To visually see the chunks in the response, we append a separator

Then, in a terminal, run:

[source, bash]
----
> curl http://localhost:8080/vertx/book
----

It should retrieve the book content.
In the output you should see the separator like:

[source, text]
----
...
The little princess had also left the tea table and followed Hélène.

“Wait a moment, I’ll get my work.... Now then, what
------------
 are you
thinking of?” she went on, turning to Prince Hippolyte. “Fetch me my
workbag.”
...
----

== Using the event bus

One of the core features of Vert.x is the https://vertx.io/docs/vertx-core/java/#event_bus[event bus].
It provides a message-based backbone to your application.
So, you can have components interacting using asynchronous message passing, and so decouple your components.
You can send a message to a single consumer, or dispatch to multiple consumers, or implement a request-reply interaction, where you send a message (request) and expect a response.
This is what we are going to use in this section.
Our `VertxResource` will send a message containing a name to the `greetings` address.
Another component will receive the message and produce the "hello $name" response.
The `VertxResource` will receive the response and return it as the HTTP response.

So, first, let's extend our `VertxResource` class with the following code:


[source, java]
----
@Inject
EventBus bus;                                                   // <1>

@GET
@Path("/hello")
public Uni<String> hello(@QueryParam("name") String name) {     // <2>
    return bus.<String>request("greetings", name)               // <3>
            .onItem().transform(response -> response.body());   // <4>
}
----
1. Inject the event bus. Alternatively you can use `vertx.eventBus()`.
2. We receive a _name_ as a query parameter
3. We use the `request` method to initiate the request-reply interaction. We send the name to the "greetings" address.
4. When the response is received, we extract the body and return it as the HTTP response

Now, we need the other side: the component receiving the name and replying.
Create the `src/main/java/org/acme/GreetingService.java` file with the following content:

[source, java]
----
package org.acme;

import io.quarkus.vertx.ConsumeEvent;

import javax.enterprise.context.ApplicationScoped;

@ApplicationScoped                          // <1>
public class GreetingService {

    @ConsumeEvent("greetings")              // <2>
    public String hello(String name) {      // <3>
        return "Hello " + name;             // <4>
    }
}
----
1. Declaring a CDI Bean in the Application scope. Quarkus will create a single instance of this class.
2. Use the `@ConsumeEvent` annotation to declare a consumer. It is possible to use the Vert.x API directly too. TODO LINK REF
3. Receive the message payload as a method parameter. The returned object will be the reply.
4. Return the response. This response is sent back to the `VertxResource` class

Let's try this.
In a terminal, run:


[source, bash]
----
> curl "http://localhost:8080/vertx/hello?name=bob"
----

You should get the expected `Hello bob` message back.

== Using Vert.x Clients

So far, we have used the Vert.x Core API.
Vert.x offers much more.
It provides a vast ecosystem.
In this section, we will see how you can use the Vert.x Web Client, a reactive HTTP client.

Note that some Quarkus extensions are wrapping Vert.x clients and manage them for you.
That's the case for the reactive data sources, Redis, mail...
That's not the case with the Web Client.

Remember, at the beginning of the guide,  we added the `smallrye-mutiny-vertx-web-client` dependency to our `pom.xml` file.
It's now time to use it.

First, we need to create an instance of `WebClient`.
Extend the `VertxResource` class with the `client` field and the creation of the web client in the constructor:

[source, java]
----
private final Vertx vertx;
private final WebClient client;            // <1>

@Inject
public VertxResource(Vertx vertx) {
    this.vertx = vertx;
    this.client = WebClient.create(vertx); // <2>
}
----
1. Store the `WebClient`, so we will be able to use it in our HTTP endpoint
2. Create the `WebClient`. Be sure to use the `io.vertx.mutiny.ext.web.client.WebClient` class

Let's now implement a new HTTP endpoint that queries the Wikipedia API to retrieve the pages about Quarkus in the different languages.
Add the following method to the `VertxResource` class:

[source, java]
----
private static final String URL = "https://en.wikipedia.org/w/api.php?action=parse&page=Quarkus&format=json&prop=langlinks";

@GET
@Path("/web")
public Uni<JsonArray> retrieveDataFromWikipedia() {                     // <1>
    return client.getAbs(URL).send()                                    // <2>
            .onItem().transform(HttpResponse::bodyAsJsonObject)         // <3>
            .onItem().transform(json -> json.getJsonObject("parse")     // <4>
                                        .getJsonArray("langlinks"));
}
----
1. This endpoint returns a JSON Array. Vert.x provides a convenient way to manipulate JSON Object and Array. More details about these in xref:vertx-reference.adoc#using-vert-x-json[the reference guide].
2. Send a `GET` request to the Wikipedia API
3. Once the response is received, extract it as a JSON Object
4. Extract the `langlinks` array from the response.

Then, invoke the endpoint using:

[source, bash]
----
> curl http://localhost:8080/vertx/web
[{"lang":"de","url":"https://de.wikipedia.org/wiki/Quarkus","langname":"German","autonym":"Deutsch","*":"Quarkus"},{"lang":"fr","url":"https://fr.wikipedia.org/wiki/Quarkus","langname":"French","autonym":"français","*":"Quarkus"}]
----

The response indicates that, in addition to the English page, there are a German and a French page about Quarkus on wikipedia.

== Going further

This guide introduced how you can use Vert.x APIs from a Quarkus application.
It's just a brief overview.
If you want to know more, check the xref:vertx-reference.adoc[reference guide about Vert.x in Quarkus].

As we have seen, the event bus is the connecting tissue of Vert.x applications.
Quarkus integrates it so different beans can interact with asynchronous messages.
This part is covered in the link:reactive-event-bus[event bus documentation].

Learn how to implement highly performant, low-overhead database applications on Quarkus with the link:reactive-sql-clients[Reactive SQL Clients].
