1. Vertx
Vertx Reactive applications on the JVM.
This module export the following services:
-
io.vertx.core.Vertx
-
io.vertx.core.eventbus.EventBus
-
io.vertx.core.file.FileSystem
1.1. Usage
1) Add the dependency:
<dependency>
<groupId>io.jooby</groupId>
<artifactId>jooby-vertx</artifactId>
<version>4.0.11</version>
</dependency>
2) Install
import io.jooby.vertx.VertxModule;
import static io.jooby.vertx.VertxHandler.vertx;
{
install(new VertxModule()); (1)
use(vertx()); (2)
get("/bus}", ctx -> {
var eb = require(EventBus.class); (3)
eventBus.publish("msg", ctx.query("msg").value("Event Bus!")); (4)
...
});
get("/*filepath", ctx -> {
var fs = require(FileSytem.class); (5)
return fs.open(ctx.path("filepath").value(), new OpenOptions()); (6)
});
}
| 1 | Install Vertx |
| 2 | Install vertx handler. Know how to render future, promise and buffer. |
| 3 | Get EventBus instance |
| 4 | Send message to msg |
| 5 | Get FileSystem |
| 6 | Open a possible large file and send it to client. |
1.2. Options
Options can be provided manually or from application.conf properties:
import io.jooby.vertx.VertxModule;
{
install(new VertxModule(new VertxOptions()
.setEventLoopSize(5)
.setWorkerPoolSize(20)
.setBlockedThreadCheckInterval(500)
.setMaxEventLoopExecuteTime(2000)
));
}
vertx.eventLoopPoolSize=5
vertx.workerPoolSize = 20
vertx.blockedThreadCheckInterval=500
vertx.maxEventLoopExecuteTime=2000
...
import io.jooby.vertx.VertxModule;
{
install(new VertxModule());
}
A clustered vertx instance can be provided at creation time:
import io.jooby.vertx.VertxModule;
{
install(new VertxModule(options -> Vertx.builder()
.with(options)
.withClusteredManager(cm)
.buildClustered()
));
}
2. Sql Client
A reactive SQL Client. Supported databases:
-
MySQL
-
PostgreSQL
These modules require a Vertx instance available in the service registry.
2.1. mysql
1) Add the dependency:
<!-- Vertx Module-->
<dependency>
<groupId>io.jooby</groupId>
<artifactId>jooby-vertx</artifactId>
<version>4.0.11</version>
</dependency>
<!-- mysql Client-->
<dependency>
<groupId>io.jooby</groupId>
<artifactId>jooby-vertx-mysql-client</artifactId>
<version>4.0.11</version>
</dependency>
2) Define connection string or key/value pairs details:
db = mysql//dbuser:secretpassword@localhost:3306/mydb
db.host = localhost
db.port = 3306
db.database = mydb
db.user = dbuser
db.password = secretpassword
3) Install
import io.jooby.vertx.VertxModule;
import io.jooby.vertx.VertxMySQLModule;
import static io.jooby.vertx.VertxHandler.vertx;
{
install(new VertxModule()); (1)
install(new VertxMySQLModule()); (2)
use(vertx()); (3)
get("/{id}", ctx -> {
var db = require(SqlClient.class); (4)
return db.preparedQuery("SELECT id, name from World where id=$1") (5)
.execute(Tuple.of(ctx.path("id").longValue()))
.map(result -> {
var row = result.iterator().next();
return new World(row.getInteger(0), row.getInteger(1));
});
});
}
| 1 | Install Vertx |
| 2 | Install Sql Client: {{sqlClient} |
| 3 | Install vertx handler. Render future, promise and buffer |
| 4 | Get SQL client instance |
| 5 | Run a database query |
To use the client version of the driver:
{
...
install(new VertxMySQLModule(MySQLBuilder::client));
...
}
2.2. postgresql
1) Add the dependency:
<!-- Vertx Module-->
<dependency>
<groupId>io.jooby</groupId>
<artifactId>jooby-vertx</artifactId>
<version>4.0.11</version>
</dependency>
<!-- postgresql Client-->
<dependency>
<groupId>io.jooby</groupId>
<artifactId>jooby-vertx-pg-client</artifactId>
<version>4.0.11</version>
</dependency>
2) Define connection string or key/value pairs details:
db = postgresql//dbuser:secretpassword@localhost:5432/mydb
db.host = localhost
db.port = 5432
db.database = mydb
db.user = dbuser
db.password = secretpassword
3) Install
import io.jooby.vertx.VertxModule;
import io.jooby.vertx.VertxPgModule;
import static io.jooby.vertx.VertxHandler.vertx;
{
install(new VertxModule()); (1)
install(new VertxPgModule()); (2)
use(vertx()); (3)
get("/{id}", ctx -> {
var db = require(SqlClient.class); (4)
return db.preparedQuery("SELECT id, name from World where id=$1") (5)
.execute(Tuple.of(ctx.path("id").longValue()))
.map(result -> {
var row = result.iterator().next();
return new World(row.getInteger(0), row.getInteger(1));
});
});
}
| 1 | Install Vertx |
| 2 | Install Sql Client: {{sqlClient} |
| 3 | Install vertx handler. Render future, promise and buffer |
| 4 | Get SQL client instance |
| 5 | Run a database query |
To use the client version of the driver:
{
...
install(new VertxPgModule(PgBuilder::client));
...
}
3. Vertx Server (Advanced)
The VertxServer allow you to share the Vertx acceptor and event loop groups within the NettyServer, so both vertx and netty web server implementation share the same resources. See for more information.
The vertx server must be manually provided at boot time (there is no service loader support for it):
import io.jooby.vertx.VertxServer;
{
get("/vertx", ctx -> {
return "Running from vertx event loop";
});
}
public static void main(String[] args) {
runApp(args, new VertxServer(), EVENT_LOOP, App::new);
}
If you run multiple applications, they all share a single Vertx instance.
|
VertxModule must NOT be installed while running on VertxServer |
One of the main benefits of running on the VertxServer is to share/reuse the event loop threads. You can run non-blocking code on the Vertx event loop thread without context switch. A good example of this is to run within
3.1. Sql Connection
These modules exist as part of the performance tests required by Techempower.
You are free to use them, but keep in mind they are for very specific kind of application.
3.1.1. MySQL
1) Add the dependency:
<!-- Vertx Module-->
<dependency>
<groupId>io.jooby</groupId>
<artifactId>jooby-vertx</artifactId>
<version>4.0.11</version>
</dependency>
<!-- MySQL Client-->
<dependency>
<groupId>io.jooby</groupId>
<artifactId>jooby-vertx-mysql-client</artifactId>
<version>4.0.11</version>
</dependency>
2) Install
import io.jooby.vertx.VertxServer;
import io.jooby.vertx.VertxMySQLConnectionModule;
import static io.jooby.vertx.VertxHandler.vertx;
{
install(new VertxMySQLConnectionModule()); (2)
use(vertx()); (3)
get("/{id}", ctx -> {
var db = require(SqlClient.class); (4)
return db.preparedQuery("SELECT id, name from World where id=$1") (5)
.execute(Tuple.of(ctx.path("id").longValue()))
.map(result -> {
var row = result.iterator().next();
return new World(row.getInteger(0), row.getInteger(1)); (6)
});
});
}
public static void main(String[] args) {
runApp(args, new VertxServer(), EVENT_LOOP, MyApp::new); (1)
}
| 1 | Install Vertx as web server |
| 2 | Install Sql connection client: {{sqlClient} |
| 3 | Install vertx handler. Render future, promise and buffer |
| 4 | Get SQL client instance, from Vertx event loop thread |
| 5 | Run a database query, from the same Vertx event loop thread |
| 6 | Run a database query, from the same Vertx event loop thread |
3.1.2. Postgres
1) Add the dependency:
<!-- Vertx Module-->
<dependency>
<groupId>io.jooby</groupId>
<artifactId>jooby-vertx</artifactId>
<version>4.0.11</version>
</dependency>
<!-- Postgres Client-->
<dependency>
<groupId>io.jooby</groupId>
<artifactId>jooby-vertx-pg-client</artifactId>
<version>4.0.11</version>
</dependency>
2) Install
import io.jooby.vertx.VertxServer;
import io.jooby.vertx.VertxPgConnectionModule;
import static io.jooby.vertx.VertxHandler.vertx;
{
install(new VertxPgConnectionModule()); (2)
use(vertx()); (3)
get("/{id}", ctx -> {
var db = require(SqlClient.class); (4)
return db.preparedQuery("SELECT id, name from World where id=$1") (5)
.execute(Tuple.of(ctx.path("id").longValue()))
.map(result -> {
var row = result.iterator().next();
return new World(row.getInteger(0), row.getInteger(1)); (6)
});
});
}
public static void main(String[] args) {
runApp(args, new VertxServer(), EVENT_LOOP, MyApp::new); (1)
}
| 1 | Install Vertx as web server |
| 2 | Install Sql connection client: {{sqlClient} |
| 3 | Install vertx handler. Render future, promise and buffer |
| 4 | Get SQL client instance, from Vertx event loop thread |
| 5 | Run a database query, from the same Vertx event loop thread |
| 6 | Run a database query, from the same Vertx event loop thread |
3.1.3. How it works?
There is an internal Verticle (one per IO threads) with a dedicated SqlConnection. This connection is only accessible from a Vertx thread any attempt to access to the connection from a non Vertx thread will result in exception.
Same applies for the PreparedStatement / PreparedQuery instances.
import io.jooby.Reified;
String SELECT_WORLD = "SELECT id, randomnumber from WORLD where id=$1";
Reified<PreparedQuery<RowSet<Row>>> PreparedQueryType =
getParameterized(PreparedQuery.class, getParameterized(RowSet.class, Row.class));
{
install(new VertxPgConnectionModule()
.preparedStatement(Map.of("selectWorld", List.of(SELECT_WORLD))) (1)
);
use(vertx()); (2)
var selectWorldQuery = ctx.require(PreparedQueryType, "selectWorld"); (3)
get("/world/{id}", ctx -> {
return selectWorldQuery.execute(Tuple.of(ctx.path("id").longValue()))
.map(
result -> {
var row = result.iterator().next();
return new World(row.getInteger(0), row.getInteger(1));
});
});
}
public static void main(String[] args) {
runApp(args, new VertxServer(), EVENT_LOOP, App::new);
}
| 1 | Created a prepared statement. This is done when Verticle is deployed |
| 2 | Add Vertx handler, so it can render Future and Promise. |
| 3 | Get a reference to the prepared statement |
The line:
var selectWorldQuery = ctx.require(PreparedQueryType, "selectWorld");
Allow you to get a reference/proxy to the prepared statement/query. The proxy will thrown an exception if you try to use from a non Vertx thread. The prepared statement is compiled when the Verticle is deployed (at application startup time).
If you work with any of the dependency injection supported framework, you can inject the prepared statement like:
@Inject
public WorldRepository(@Named("selectWorld") PreparedQuery<RowSet<Row>> selectWorld) {
this.selectWorld = selectWorld;
}