Chapter 1. Introduction to Eclipse Vert.x

1.1. What is Eclipse Vert.x

Eclipse Vert.x is a toolkit for writing reactive, non-blocking, asynchronous applications that run on the JVM (Java Virtual Machine). Eclipse Vert.x provides a non-prescriptive and flexible way to write efficient, multi-language (polyglot) applications. Eclipse Vert.x is also designed to be truly cloud-native by efficiently allowing many processes to switch between one or very few threads. This allows Eclipse Vert.x applications and services to more effectively use their CPU quotas in cloud environments and avoids the unnecessary overhead caused when creating new threads. Check out Additional Resources for further reading on Eclipse Vert.x.

Using the Eclipse Vert.x runtime in OpenShift makes it simpler and easier to build reactive systems with Eclipse Vert.x. The Eclipse Vert.x runtime enables you to run Eclipse Vert.x applications and services in OpenShift while providing all the advantages and conveniences of the OpenShift platform such as rolling updates, service discovery, and canary deployments. OpenShift also makes it easier for your applications to implement common microservice patterns such as externalized configuration, health check, circuit breaker, and failover.

1.2. Key Eclipse Vert.x concepts

Cloud- and Container-Native Applications

Cloud-native applications are one of the key technological concepts behind microservices. They are designed to form distributed systems consisting of decoupled components that often run inside containers, on top of clusters containing a large number of nodes. These applications are intended to be resistant to failure of individual components, and to be updated without requiring service downtime. Systems based on cloud-native applications rely on automated deployment, scaling, and administrative and maintenance tasks. Management and administration tasks are often carried out at cluster level using off-the-shelf management and orchestration tools, rather than on the level of individual machines.

Reactive Systems

A reactive system, as defined in the reactive manifesto, is a distributed systems with the following characteristics:

Elastic
The system remains responsive under varying workload, with individual components scaled and load-balanced as necessary to accommodate the differences in workload. Elastic application deliver the same quality of service regardless of the number of requests they receive at the same time.
Resilient
The system remains responsive when any of its individual components fails. Components are isolated from each other, with each individual component able to quickly recover after failure occurs. Failure of a single component should never prevent other components from functioning properly for a longer time. This prevents cascading failure, where the failure of an isolated component causes other components to become blocked and gradually fail.
Responsive
Responsive systems are designed to always respond to requests in a reasonable amount of time to ensure a consistent quality of service. To maintain responsiveness, the communication channel between the applications must never be blocked.
Message-Driven
The individual components of an application use asynchronous message-passing to communicate with each other. The components first detect each other using service discovery. If an event takes place (such as a mouse click or a search query) on a service, the service sends out a message over a common channel (the event bus). The messages is in turn caught and handled by the respective component.

Reactive Systems can be understood as “distributed systems done right”. They are designed with asynchrony as their key property in mind.

Reactive Programming

While the concept of reactive systems describes the architecture of a distributed system, reactive programming refers to practices that make applications reactive at the code level. Reactive programming is a development model to write asynchronous and event-driven applications. In reactive applicatios, the code reacts to events or messages.

There are several implementations of reactive programming, from the simplest ones using callbacks, to more complex ones, such as the Reactive Extensions (Rx), and coroutines. The Reactive Extensions (Rx) is the most well-known form of reactive programming in Java, thanks to the frequently-used RxJava library.

For further reading on reactive systems, reactive programming, and reactive extensions, see the Additional Resources section.

1.3. Configuring your application to use Eclipse Vert.x

Reference the Eclipse Vert.x BOM (Bill of Materials) artifact in the pom.xml file at the root directory of your application.

Prerequisites

  • A Maven-based application

Procedure

  1. Open the pom.xml file, add the io.vertx:vertx-dependencies artifact to the <dependencyManagement> section, and specify the <type>pom</type> and <scope>import</scope>:

    <project>
      ...
      <dependencyManagement>
        <dependencies>
          <dependency>
            <groupId>io.vertx</groupId>
            <artifactId>vertx-dependencies</artifactId>
            <version>${vertx.version}</version>
            <type>pom</type>
            <scope>import</scope>
          </dependency>
        </dependencies>
      </dependencyManagement>
      ...
    </project>
  2. Include the following properties to track the version of Eclipse Vert.x and the Vert.x Maven Plugin you are using:

    <project>
      ...
      <properties>
        <vertx.version>${vertx.version}</vertx.version>
        <vertx-maven-plugin.version>${vertx-maven-plugin.version}</vertx-maven-plugin.version>
      </properties>
      ...
    </project>
  3. Reference vertx-maven-plugin as the plugin used to package your application:

    <project>
      ...
      <build>
        <plugins>
            ...
            <plugin>
                <groupId>io.reactiverse</groupId>
                <artifactId>vertx-maven-plugin</artifactId>
                <version>${vertx-maven-plugin.version}</version>
                <executions>
                    <execution>
                        <id>vmp</id>
                        <goals>
                            <goal>initialize</goal>
                            <goal>package</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <redeploy>true</redeploy>
                </configuration>
            </plugin>
            ...
        </plugins>
      </build>
      ...
    </project>
  4. Include repositories and pluginRepositories to specify the repositories that contain the artifacts and plugins to build your application:

    <project>
    ...
      <repositories>
        <repository>
          <id>redhat-ga</id>
          <name>Red Hat GA Repository</name>
          <url>https://maven.repository.redhat.com/ga/</url>
        </repository>
      </repositories>
      <pluginRepositories>
        <pluginRepository>
          <id>redhat-ga</id>
          <name>Red Hat GA Repository</name>
          <url>https://maven.repository.redhat.com/ga/</url>
        </pluginRepository>
      </pluginRepositories>
    ...
    </project>

Additional resources

  • For more information about packaging your Eclipse Vert.x application, see the Vert.x Maven Plugin documentation.

1.4. Configuring your Eclipse Vert.x application to use Agroal

Starting with Eclipse Vert.x release 3.5.1.redhat-003, Agroal replaced C3PO as the default JDBC connection pool. C3PO and Agroal use different property names and upgrading to a newer release of Eclipse Vert.x might break the JDBC connection pool configuration of your Eclipse Vert.x applications. Update the property names in the configuration of your JDBC connection pool to avoid this issue.

Note

To continue using C3P0 as the JDBC connection pool for your application, set the value of the provider_class property in your JDBC connection pool configuration to io.vertx.ext.jdbc.spi.impl.C3P0DataSourceProvider.

Procedure

  1. Update the following property names within your JDBC connection pool configuration to match the connection pool you use:
C3P0 property nameAgroal property name

url

jdbcUrl

driver_class

driverClassName

user

principal

password

credential

castUUID

castUUID

Additional information

  • Example JDBC connection pool configuration using C3P0:

    JsonObject config = new JsonObject()
    	.put("url", JDBC_URL)
    	// set C3P0 as the JDBC connection pool:
    	.put("provider_class", "io.vertx.ext.jdbc.spi.impl.C3P0DataSourceProvider")
    	.put("driver_class", "org.postgresql.Driver")
    	.put("user", JDBC_USER)
    	.put("password", JDBC_PASSWORD)
    	.put("castUUID", true);
  • Example JDBC connection pool configuration using Agroal:

    JsonObject config = new JsonObject()
    	.put("jdbcUrl", JDBC_URL)
    	.put("driverClassName", "org.postgresql.Driver")
    	.put("principal", JDBC_USER)
    	.put("credential", JDBC_PASSWORD)
    	.put("castUUID", true);