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

include::./attributes.adoc[]

Eclipse https://vertx.io[Vert.x] is a toolkit for building reactive applications.
It is designed to be lightweight and embeddable.
Vert.x defines a reactive execution model and provides a large ecosystem.

Quarkus is based on Vert.x, and almost all network-related features rely on Vert.x.
While lots of reactive features from Quarkus don't _show_ Vert.x, it's used underneath.
Quarkus also integrates smoothly with the Vert.x event bus (to enable asynchronous messaging passing between application components) and some reactive clients.
You can also use various Vert.x APIs in your Quarkus application, such as deploying _verticles_, instantiating clients...


== Installing

To access Vert.x, well, you need to enable the `vertx` extension to use this feature.
If you are creating a new project, set the `extensions` parameter are follows:

[source, shell, subs=attributes+]
----
mvn io.quarkus:quarkus-maven-plugin:{quarkus-version}:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=vertx-quickstart \
    -Dextensions="vertx"
cd vertx-quickstart
----

If you have an already created project, the `vertx` extension can be added to an existing Quarkus project with
the `add-extension` command:

[source,shell]
----
./mvnw quarkus:add-extension -Dextensions="vertx"
----

Otherwise, you can manually add this to the dependencies section of your `pom.xml` file:

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

== Accessing Vert.x

Once the extension has been added, you can access the _managed_ Vert.x instance using `@Inject`:

[source, java]
----
@Inject Vertx vertx;
----

If you are familiar with Vert.x, you know that Vert.x provides different API models.
For instance _bare_ Vert.x uses callbacks, the Mutiny variants uses `Uni` and `Multi`, the RX Java 2 version uses `Single`, `Maybe`, `Completable`, `Observable` and `Flowable`...

Quarkus provides 4 Vert.x APIs:

[options="header"]
|===

| Name | Code | Description

| _bare_ | `@Inject io.vertx.core.Vertx vertx` | _bare_ Vert.x instance, the API uses callbacks.

| https://smallrye.io/smallrye-mutiny/[Mutiny] | `@Inject io.vertx.mutiny.core.Vertx vertx` | The Mutiny API for Vert.x.

| RX Java 2 | `@Inject io.vertx.reactivex.core.Vertx vertx` | RX Java 2 Vert.x, the API uses RX Java 2 types (deprecated).

| _Axle_ | `@Inject io.vertx.axle.core.Vertx vertx` | Axle Vert.x, the API uses `CompletionStage` and `Reactive Streams` (deprecated).

|===

TIP: You may inject any of the 4 flavors of `Vertx` as well as the `EventBus` in your Quarkus application beans: `bare`, `Mutiny`, `Axle`, `RxJava2`.
They are just shims and rely on a single _managed_ Vert.x instance.

You will pick one or the other depending on your use cases.

- `bare`: for advanced usage or if you have existing Vert.x code you want to reuse in your Quarkus application
- `mutiny`: Mutiny is an event-driven reactive programming API. It uses 2 types: `Uni` and `Multi`. This is the recommended API.
- `Axle`: works well with Quarkus and MicroProfile APIs (`CompletionStage` for single results and `Publisher` for streams) - deprecated, it is recommended to switch to Mutiny
- `Rx Java 2`: when you need support for a wide range of data transformation operators on your streams - deprecated, it is recommended to switch to Mutiny

The following snippets illustrate the difference between these 4 APIs:

[source, java]
----
// Bare Vert.x:
vertx.fileSystem().readFile("lorem-ipsum.txt", ar -> {
    if (ar.succeeded()) {
        System.out.println("Content:" + ar.result().toString("UTF-8"));
    } else {
        System.out.println("Cannot read the file: " + ar.cause().getMessage());
    }
});

// Mutiny Vert.x:
vertx.fileSystem().readFile("lorem-ipsum.txt")
    .onItem().apply(buffer -> buffer.toString("UTF-8"))
    .subscribe(
            content -> System.out.println("Content: " + content),
            err -> System.out.println("Cannot read the file: " + err.getMessage())
    );

// Rx Java 2 Vert.x
vertx.fileSystem().rxReadFile("lorem-ipsum.txt")
    .map(buffer -> buffer.toString("UTF-8"))
    .subscribe(
            content -> System.out.println("Content: " + content),
            err -> System.out.println("Cannot read the file: " + err.getMessage())
    );

// Axle API:
vertx.fileSystem().readFile("lorem-ipsum.txt")
    .thenApply(buffer -> buffer.toString("UTF-8"))
    .whenComplete((content, err) -> {
        if (err != null) {
            System.out.println("Cannot read the file: " + err.getMessage());
        } else {
            System.out.println("Content: " + content);
        }
    });
----

== Using Vert.x in Reactive JAX-RS resources

Quarkus web resources support asynchronous processing and streaming results over https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events[server-sent events].

=== Asynchronous processing

To asynchronously handle the HTTP request, the endpoint method must return a `java.util.concurrent.CompletionStage` or an `io.smallrye.mutiny.Uni` (requires the `quarkus-resteasy-mutiny` extension):

[source,java]
----
@Path("/lorem")
public class GreetingResource {

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public Uni<String> doSomethingAsync() {
        // Mimic an asynchronous computation.
        return Uni.createFrom()
                .item(() -> "Hello!")
                .onItem().delayIt().by(Duration.ofMillis(10));
    }
}
----


[source, shell]
----
./mvnw compile quarkus:dev
----

Then, open your browser to 'http://localhost:8080/lorem' and you should get the message.

So far so good.
Now let's use the Vert.x API instead of this artificial delay:

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

import io.smallrye.mutiny.Uni;
import io.vertx.mutiny.core.Vertx;

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("/lorem")
public class GreetingResource {

    @Inject
    Vertx vertx;

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public Uni<String> doSomethingAsync() {
        return vertx.fileSystem().readFile("/META-INF/resources/lorem.txt")
                .onItem().apply(b -> b.toString("UTF-8"));
    }
}
----

In this code, we inject the `vertx` instance (`io.vertx.mutiny.core.Vertx`) and read a file from the file system.

Create the `src/main/resources/META_INF/resources/lorem.txt` file with the following content:

[source,text]
----
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
----

Then, refresh the page, you should see the _lorem ipsum_ text.

=== Streaming using Server-Sent Events

Quarkus web resources that need to send content as https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events[server-sent events] must have a method:

* declaring the `text/event-stream` response content type
* returning a https://www.reactive-streams.org/[Reactive Streams] `Publisher` or Mutiny `Multi`  (requires the `quarkus-resteasy-mutiny` extension)

In practice, a streaming greeting service would look like:

[source,java]
----
@Path("/hello")
public class StreamingResource {

    @GET
    @Produces(MediaType.SERVER_SENT_EVENTS)
    @Path("/{name}")
    public Multi<String> greeting(@PathParam String name) {
        // TODO: create a Reactive Streams publisher or a Mutiny Multi
        return publisher;
    }
}
----

Now we just need to return our `Publisher` or `Multi`:

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

import io.smallrye.mutiny.Multi;
import io.vertx.mutiny.core.Vertx;
import org.jboss.resteasy.annotations.jaxrs.PathParam;

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;
import java.util.Date;

@Path("/stream")
public class StreamingResource {

    @Inject
    Vertx vertx;

    @GET
    @Produces(MediaType.SERVER_SENT_EVENTS)
    @Path("/{name}")
    public Multi<String> greeting(@PathParam String name) {
        return vertx.periodicStream(2000).toMulti()
                .map(l -> String.format("Hello %s! (%s)%n", name, new Date()));
    }
}
----

The server side is ready.
In order to see the result in the browser, we need a web page.

[source,html]
.META-INF/resources/streaming.html
----
<!doctype html>
<html>
<head>
    <meta charset="utf-8"/>
    <title>SSE with Vert.x - Quarkus</title>
    <script type="application/javascript" src="streaming.js"></script>
</head>
<body>
<div id="container"></div>
</body>
</html>
----

Our web page just has an empty `<div>` container.
The magic, as always, lies in the Javascript code:

[source,javascript]
.META-INF/resources/streaming.js
----
if (!!window.EventSource) {
    var eventSource = new EventSource("/stream/Quarkus");
    eventSource.onmessage = function (event) {
        var container = document.getElementById("container");
        var paragraph = document.createElement("p");
        paragraph.innerHTML = event.data;
        container.appendChild(paragraph);
    };
} else {
    window.alert("EventSource not available on this browser.")
}
----

IMPORTANT: Most browsers support SSE but some don't.
More about this in  Mozilla's https://developer.mozilla.org/en-US/docs/Web/API/EventSource#Browser_compatibility[SSE browser-compatibility list].

Navigate to http://localhost:8080/streaming.html.
A new greeting should show-up every 2 seconds.

[source, text]
----
Hello Quarkus! (Wed Feb 12 17:13:55 CET 2020)

Hello Quarkus! (Wed Feb 12 17:13:57 CET 2020)

Hello Quarkus! (Wed Feb 12 17:13:59 CET 2020)

Hello Quarkus! (Wed Feb 12 17:14:01 CET 2020)

Hello Quarkus! (Wed Feb 12 17:14:03 CET 2020)

...
----

=== Using Vert.x JSON

Vert.x API heavily relies on JSON, namely the `io.vertx.core.json.JsonObject` and `io.vertx.core.json.JsonArray` types.
They are both supported as Quarkus web resource request and response bodies.

Consider these endpoints:

[source,java]
----
@Path("/hello")
@Produces(MediaType.APPLICATION_JSON)
public class VertxJsonResource {

    @GET
    @Path("{name}/object")
    public JsonObject jsonObject(@PathParam String name) {
        return new JsonObject().put("Hello", name);
    }

    @GET
    @Path("{name}/array")
    public JsonArray jsonArray(@PathParam String name) {
        return new JsonArray().add("Hello").add(name);
    }
}
----

In your browser, navigate to http://localhost:8080/hello/Quarkus/object. You should see:

[source, text]
----
{"Hello":"Quarkus"}
----

Then, navigate to http://localhost:8080/hello/Quarkus/array:

[source, text]
----
["Hello","Quarkus"]
----

Needless to say, this works equally well when the JSON content is a request body or is wrapped in a `Uni`, `Multi`, `CompletionStage` or `Publisher`.

== Using Vert.x Clients

As you can inject a Vert.x instance, you can use Vert.x clients in a Quarkus application.
This section gives an example with the `WebClient`.

=== Picking the right dependency

Depending on the API model you want to use you need to add the right dependency to your `pom.xml` file:

[source, xml, subs=attributes+]
----
<!-- bare API -->
<dependency>
  <groupId>io.vertx</groupId>
  <artifactId>vertx-web-client</artifactId>
</dependency>

<!-- Mutiny API -->
<dependency>
  <groupId>io.smallrye.reactive</groupId>
  <artifactId>smallrye-mutiny-vertx-web-client</artifactId>
</dependency>

<!-- Axle API -->
<dependency>
  <groupId>io.smallrye.reactive</groupId>
  <artifactId>smallrye-axle-web-client</artifactId>
</dependency>

<!-- RX Java 2 API -->
<dependency>
  <groupId>io.vertx</groupId>
  <artifactId>vertx-rx-java2</artifactId>
</dependency>
----

NOTE: The `vertx-rx-java2` provides the RX Java 2 API for the whole Vert.x stack, not only the web client.

In this guide, we are going to use the Axle API, so:

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

Now, create a new resource in your project with the following content:

[source, java]
.src/main/java/org/acme/vertx/ResourceUsingWebClient.java
----
package org.acme.vertx;


import javax.annotation.PostConstruct;
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;

import io.smallrye.mutiny.Uni;
import org.jboss.resteasy.annotations.jaxrs.PathParam;

import io.vertx.mutiny.core.Vertx;
import io.vertx.mutiny.ext.web.client.WebClient;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.client.WebClientOptions;

@Path("/fruit-data")
public class ResourceUsingWebClient {

    @Inject
    Vertx vertx;

    private WebClient client;

    @PostConstruct
    void initialize() {
        this.client = WebClient.create(vertx,
                new WebClientOptions().setDefaultHost("fruityvice.com")
                    .setDefaultPort(443).setSsl(true).setTrustAll(true));
    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("/{name}")
    public Uni<JsonObject> getFruitData(@PathParam("name") String name) {
        return client.get("/api/fruit/" + name)
                .send()
                .onItem().apply(resp -> {
                    if (resp.statusCode() == 200) {
                        return resp.bodyAsJsonObject();
                    } else {
                        return new JsonObject()
                                .put("code", resp.statusCode())
                                .put("message", resp.bodyAsString());
                    }
                });
    }

}

----

This resource creates a `WebClient` and upon request use this client to invoke the _fruityvice_ API.
Depending on the result the response is forwarded as it's received, or a new JSON object is created with the status and body.
The `WebClient` is obviously asynchronous (and non-blocking), to the endpoint returns a `Uni`.

Run the application with:

[source, shell]
----
./mvnw compile quarkus:dev
----

And then, open a browser to: `http://localhost:8080/fruit-data/pear`. You should get some details about pears.

The application can also run as a native executable.
But, first, we need to instruct Quarkus to enable _ssl_.
Open the `src/main/resources/application.properties` and add:

[source]
----
quarkus.ssl.native=true
----

Then, create the native executable with:

[source, shell]
----
./mvnw package -Pnative
----

== Read only deployment environments

In environments with read only file systems you may receive errors of the form:

```
java.lang.IllegalStateException: Failed to create cache dir
```

Assuming `/tmp/` is writeable this can be fixed by setting the `vertx.cacheDirBase` property to point to a directory in `/tmp/` for instance in OpenShift by creating an environment variable `JAVA_OPTS` with the value `-Dvertx.cacheDirBase=/tmp/vertx`.

== Going further

There are many other facets of Quarkus using Vert.x underneath:

* 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-messaging[Async Message Passing documentation].

* Data streaming and Apache Kafka are a important parts of modern systems.
Quarkus integrates data streaming using Reactive Messaging.
More details on link:kafka[Interacting with Kafka].

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