Browse Source

jooby: upgrade 3.x (#8294)

- upgrade to latest version
- rename JaxrsApp => MvcApp
- update posgress tests
- version bump
Edgar Espina 2 years ago
parent
commit
b4c2b36f53

+ 1 - 0
frameworks/Java/jooby/.gitignore

@@ -0,0 +1 @@
+application.dev.conf

+ 3 - 3
frameworks/Java/jooby/benchmark_config.json

@@ -47,7 +47,7 @@
       "display_name": "jooby-netty",
       "display_name": "jooby-netty",
       "versus": "netty"
       "versus": "netty"
     },
     },
-    "jaxrs": {
+    "mvc": {
       "json_url": "/json",
       "json_url": "/json",
       "plaintext_url": "/plaintext",
       "plaintext_url": "/plaintext",
       "db_url": "/db",
       "db_url": "/db",
@@ -66,7 +66,7 @@
       "orm": "Raw",
       "orm": "Raw",
       "webserver": "None",
       "webserver": "None",
       "os": "Linux",
       "os": "Linux",
-      "notes": "Jooby JAXRS using Undertow",
+      "notes": "Jooby MVC using Undertow",
       "display_name": "jooby-jaxrs",
       "display_name": "jooby-jaxrs",
       "versus": "undertow"
       "versus": "undertow"
     },
     },
@@ -112,7 +112,7 @@
       "os": "Linux",
       "os": "Linux",
       "notes": "Jooby with Reactive PG client",
       "notes": "Jooby with Reactive PG client",
       "display_name": "jooby-pgclient",
       "display_name": "jooby-pgclient",
-      "versus": "undertow"
+      "versus": "netty"
     }
     }
   }]
   }]
 }
 }

+ 1 - 1
frameworks/Java/jooby/config.toml

@@ -67,7 +67,7 @@ platform = "Jetty"
 webserver = "None"
 webserver = "None"
 versus = "jetty"
 versus = "jetty"
 
 
-[jaxrs]
+[mvc]
 urls.plaintext = "/plaintext"
 urls.plaintext = "/plaintext"
 urls.json = "/json"
 urls.json = "/json"
 urls.db = "/db"
 urls.db = "/db"

+ 0 - 15
frameworks/Java/jooby/jooby-jaxrs.dockerfile

@@ -1,15 +0,0 @@
-FROM maven:3.6.1-jdk-11-slim as maven
-WORKDIR /jooby
-COPY pom.xml pom.xml
-COPY src src
-COPY public public
-RUN mvn package -q -P undertow
-
-FROM openjdk:11.0.3-jdk-slim
-WORKDIR /jooby
-COPY --from=maven /jooby/target/jooby.jar app.jar
-COPY conf conf
-
-EXPOSE 8080
-
-CMD ["java", "-server", "-Xms4g", "-Xmx4g", "-XX:+AggressiveOpts", "-XX:-UseBiasedLocking", "-XX:+UseStringDeduplication", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-cp", "app.jar", "com.techempower.JaxrsApp"]

+ 3 - 7
frameworks/Java/jooby/jooby-jetty.dockerfile

@@ -1,15 +1,11 @@
-FROM maven:3.6.1-jdk-11-slim as maven
+FROM maven:3.9.0-eclipse-temurin-17
 WORKDIR /jooby
 WORKDIR /jooby
 COPY pom.xml pom.xml
 COPY pom.xml pom.xml
 COPY src src
 COPY src src
 COPY public public
 COPY public public
-RUN mvn package -q -P jetty
-
-FROM openjdk:11.0.3-jdk-slim
-WORKDIR /jooby
-COPY --from=maven /jooby/target/jooby.jar app.jar
 COPY conf conf
 COPY conf conf
+RUN mvn package -q -P jetty
 
 
 EXPOSE 8080
 EXPOSE 8080
 
 
-CMD ["java", "-server", "-Xms4g", "-Xmx4g", "-XX:+AggressiveOpts", "-XX:-UseBiasedLocking", "-XX:+UseStringDeduplication", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-jar", "app.jar"]
+CMD ["java", "-server", "-Xms2g", "-Xmx2g", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-jar", "target/jooby.jar"]

+ 11 - 0
frameworks/Java/jooby/jooby-mvc.dockerfile

@@ -0,0 +1,11 @@
+FROM maven:3.9.0-eclipse-temurin-17
+WORKDIR /jooby
+COPY pom.xml pom.xml
+COPY src src
+COPY public public
+COPY conf conf
+RUN mvn package -q -P undertow
+
+EXPOSE 8080
+
+CMD ["java", "-server", "-Xms2g", "-Xmx2g", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-cp", "target/jooby.jar", "com.techempower.MvcApp"]

+ 3 - 7
frameworks/Java/jooby/jooby-netty.dockerfile

@@ -1,15 +1,11 @@
-FROM maven:3.6.1-jdk-11-slim as maven
+FROM maven:3.9.0-eclipse-temurin-17
 WORKDIR /jooby
 WORKDIR /jooby
 COPY pom.xml pom.xml
 COPY pom.xml pom.xml
 COPY src src
 COPY src src
 COPY public public
 COPY public public
-RUN mvn package -q -P netty
-
-FROM openjdk:11.0.3-jdk-slim
-WORKDIR /jooby
-COPY --from=maven /jooby/target/jooby.jar app.jar
 COPY conf conf
 COPY conf conf
+RUN mvn package -q -P netty
 
 
 EXPOSE 8080
 EXPOSE 8080
 
 
-CMD ["java", "-server", "-Xms4g", "-Xmx4g", "-XX:+AggressiveOpts", "-XX:-UseBiasedLocking", "-XX:+UseStringDeduplication", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-jar", "app.jar"]
+CMD ["java", "-server", "-Xms2g", "-Xmx2g", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-Dio.netty.disableHttpHeadersValidation=true", "-Dio.netty.buffer.checkBounds=false", "-Dio.netty.buffer.checkAccessible=false", "-jar", "target/jooby.jar"]

+ 3 - 7
frameworks/Java/jooby/jooby-pgclient.dockerfile

@@ -1,15 +1,11 @@
-FROM maven:3.6.1-jdk-11-slim as maven
+FROM maven:3.9.0-eclipse-temurin-17
 WORKDIR /jooby
 WORKDIR /jooby
 COPY pom.xml pom.xml
 COPY pom.xml pom.xml
 COPY src src
 COPY src src
 COPY public public
 COPY public public
-RUN mvn package -q -P netty
-
-FROM openjdk:11.0.3-jdk-slim
-WORKDIR /jooby
-COPY --from=maven /jooby/target/jooby.jar app.jar
 COPY conf conf
 COPY conf conf
+RUN mvn package -q -P netty
 
 
 EXPOSE 8080
 EXPOSE 8080
 
 
-CMD ["java", "-server", "-Xms4g", "-Xmx4g", "-XX:+AggressiveOpts", "-XX:-UseBiasedLocking", "-XX:+UseStringDeduplication", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-cp", "app.jar", "com.techempower.ReactivePg"]
+CMD ["java", "-server", "-Xms2g", "-Xmx2g", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-Dio.netty.disableHttpHeadersValidation=true", "-Dio.netty.buffer.checkBounds=false", "-Dio.netty.buffer.checkAccessible=false", "-cp", "target/jooby.jar", "com.techempower.ReactivePg"]

+ 4 - 7
frameworks/Java/jooby/jooby.dockerfile

@@ -1,15 +1,12 @@
-FROM maven:3.6.1-jdk-11-slim as maven
+FROM maven:3.9.0-eclipse-temurin-17
 WORKDIR /jooby
 WORKDIR /jooby
 COPY pom.xml pom.xml
 COPY pom.xml pom.xml
 COPY src src
 COPY src src
 COPY public public
 COPY public public
-RUN mvn package -q -P undertow
-
-FROM openjdk:11.0.3-jdk-slim
-WORKDIR /jooby
-COPY --from=maven /jooby/target/jooby.jar app.jar
 COPY conf conf
 COPY conf conf
 
 
+RUN mvn package -q -P undertow
+
 EXPOSE 8080
 EXPOSE 8080
 
 
-CMD ["java", "-server", "-Xms4g", "-Xmx4g", "-XX:+AggressiveOpts", "-XX:-UseBiasedLocking", "-XX:+UseStringDeduplication", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-jar", "app.jar"]
+CMD ["java", "-server", "-Xms2g", "-Xmx2g", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-jar", "target/jooby.jar"]

+ 27 - 67
frameworks/Java/jooby/pom.xml

@@ -6,47 +6,45 @@
 
 
   <artifactId>jooby</artifactId>
   <artifactId>jooby</artifactId>
   <groupId>com.techempower</groupId>
   <groupId>com.techempower</groupId>
-  <version>2.0</version>
+  <version>3.0</version>
 
 
   <name>jooby</name>
   <name>jooby</name>
 
 
   <properties>
   <properties>
-    <jooby.version>2.9.5</jooby.version>
-    <netty.version>4.1.94.Final</netty.version>
-    <dsl-json.version>1.9.5</dsl-json.version>
-    <postgresql.version>42.4.3</postgresql.version>
+    <jooby.version>3.0.0</jooby.version>
+    <dsl-json.version>1.10.0</dsl-json.version>
+    <postgresql.version>42.6.0</postgresql.version>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-    <maven.compiler.source>11</maven.compiler.source>
-    <maven.compiler.target>11</maven.compiler.target>
+    <maven.compiler.source>17</maven.compiler.source>
+    <maven.compiler.target>17</maven.compiler.target>
 
 
     <!-- Startup class -->
     <!-- Startup class -->
     <application.class>com.techempower.App</application.class>
     <application.class>com.techempower.App</application.class>
   </properties>
   </properties>
 
 
   <dependencies>
   <dependencies>
-    <dependency>
-      <groupId>jakarta.ws.rs</groupId>
-      <artifactId>jakarta.ws.rs-api</artifactId>
-    </dependency>
-
     <!-- jdbc -->
     <!-- jdbc -->
     <dependency>
     <dependency>
       <groupId>io.jooby</groupId>
       <groupId>io.jooby</groupId>
       <artifactId>jooby-hikari</artifactId>
       <artifactId>jooby-hikari</artifactId>
+      <version>${jooby.version}</version>
     </dependency>
     </dependency>
 
 
     <!-- rocker -->
     <!-- rocker -->
     <dependency>
     <dependency>
       <groupId>io.jooby</groupId>
       <groupId>io.jooby</groupId>
       <artifactId>jooby-rocker</artifactId>
       <artifactId>jooby-rocker</artifactId>
+      <version>${jooby.version}</version>
     </dependency>
     </dependency>
 
 
     <!-- mySQL -->
     <!-- mySQL -->
     <dependency>
     <dependency>
-      <groupId>mysql</groupId>
-      <artifactId>mysql-connector-java</artifactId>
+      <groupId>com.mysql</groupId>
+      <artifactId>mysql-connector-j</artifactId>
+      <version>8.0.33</version>
     </dependency>
     </dependency>
 
 
+
     <!-- postgresql -->
     <!-- postgresql -->
     <dependency>
     <dependency>
       <groupId>org.postgresql</groupId>
       <groupId>org.postgresql</groupId>
@@ -57,7 +55,7 @@
     <dependency>
     <dependency>
       <groupId>io.vertx</groupId>
       <groupId>io.vertx</groupId>
       <artifactId>vertx-pg-client</artifactId>
       <artifactId>vertx-pg-client</artifactId>
-      <version>3.9.2</version>
+      <version>4.4.4</version>
     </dependency>
     </dependency>
 
 
     <!-- json -->
     <!-- json -->
@@ -74,7 +72,7 @@
       <plugin>
       <plugin>
         <groupId>org.codehaus.mojo</groupId>
         <groupId>org.codehaus.mojo</groupId>
         <artifactId>build-helper-maven-plugin</artifactId>
         <artifactId>build-helper-maven-plugin</artifactId>
-        <version>3.2.0</version>
+        <version>3.3.0</version>
         <executions>
         <executions>
           <execution>
           <execution>
             <id>add-source</id>
             <id>add-source</id>
@@ -112,7 +110,7 @@
       <plugin>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-compiler-plugin</artifactId>
         <artifactId>maven-compiler-plugin</artifactId>
-        <version>3.8.1</version>
+        <version>3.11.0</version>
         <configuration>
         <configuration>
           <annotationProcessorPaths>
           <annotationProcessorPaths>
             <path>
             <path>
@@ -132,7 +130,7 @@
       <plugin>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-shade-plugin</artifactId>
         <artifactId>maven-shade-plugin</artifactId>
-        <version>3.2.4</version>
+        <version>3.4.1</version>
         <executions>
         <executions>
           <execution>
           <execution>
             <id>uber-jar</id>
             <id>uber-jar</id>
@@ -150,6 +148,16 @@
                   <mainClass>${application.class}</mainClass>
                   <mainClass>${application.class}</mainClass>
                 </transformer>
                 </transformer>
               </transformers>
               </transformers>
+              <filters>
+                <filter>
+                  <artifact>*:*</artifact>
+                  <excludes>
+                    <exclude>META-INF/*.SF</exclude>
+                    <exclude>META-INF/*.DSA</exclude>
+                    <exclude>META-INF/*.RSA</exclude>
+                  </excludes>
+                </filter>
+              </filters>
             </configuration>
             </configuration>
           </execution>
           </execution>
         </executions>
         </executions>
@@ -163,7 +171,7 @@
       <dependencies>
       <dependencies>
         <dependency>
         <dependency>
           <groupId>io.jooby</groupId>
           <groupId>io.jooby</groupId>
-          <artifactId>jooby-utow</artifactId>
+          <artifactId>jooby-undertow</artifactId>
           <version>${jooby.version}</version>
           <version>${jooby.version}</version>
         </dependency>
         </dependency>
       </dependencies>
       </dependencies>
@@ -183,54 +191,6 @@
     <profile>
     <profile>
       <id>netty</id>
       <id>netty</id>
       <dependencies>
       <dependencies>
-        <dependency>
-          <groupId>io.netty</groupId>
-          <artifactId>netty-common</artifactId>
-          <version>${netty.version}</version>
-        </dependency>
-
-        <dependency>
-          <groupId>io.netty</groupId>
-          <artifactId>netty-buffer</artifactId>
-          <version>${netty.version}</version>
-        </dependency>
-
-        <dependency>
-          <groupId>io.netty</groupId>
-          <artifactId>netty-handler</artifactId>
-          <version>${netty.version}</version>
-        </dependency>
-
-        <dependency>
-          <groupId>io.netty</groupId>
-          <artifactId>netty-codec-http</artifactId>
-          <version>${netty.version}</version>
-        </dependency>
-
-        <dependency>
-          <groupId>io.netty</groupId>
-          <artifactId>netty-transport</artifactId>
-          <version>${netty.version}</version>
-        </dependency>
-
-        <dependency>
-          <groupId>io.netty</groupId>
-          <artifactId>netty-transport-native-epoll</artifactId>
-          <version>${netty.version}</version>
-        </dependency>
-
-        <dependency>
-          <groupId>io.netty</groupId>
-          <artifactId>netty-transport-native-kqueue</artifactId>
-          <version>${netty.version}</version>
-          <classifier>osx-x86_64</classifier>
-        </dependency>
-        <dependency>
-          <groupId>io.netty</groupId>
-          <artifactId>netty-transport-native-epoll</artifactId>
-          <version>${netty.version}</version>
-          <classifier>linux-x86_64</classifier>
-        </dependency>
         <dependency>
         <dependency>
           <groupId>io.jooby</groupId>
           <groupId>io.jooby</groupId>
           <artifactId>jooby-netty</artifactId>
           <artifactId>jooby-netty</artifactId>

+ 1 - 1
frameworks/Java/jooby/src/main/java/com/techempower/JaxrsApp.java → frameworks/Java/jooby/src/main/java/com/techempower/MvcApp.java

@@ -8,7 +8,7 @@ import javax.sql.DataSource;
 import static io.jooby.ExecutionMode.EVENT_LOOP;
 import static io.jooby.ExecutionMode.EVENT_LOOP;
 import static io.jooby.Jooby.runApp;
 import static io.jooby.Jooby.runApp;
 
 
-public class JaxrsApp {
+public class MvcApp {
   public static void main(String[] args) {
   public static void main(String[] args) {
     runApp(args, EVENT_LOOP, app -> {
     runApp(args, EVENT_LOOP, app -> {
       /** Database: */
       /** Database: */

+ 106 - 0
frameworks/Java/jooby/src/main/java/com/techempower/PgClient.java

@@ -0,0 +1,106 @@
+package com.techempower;
+
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
+import java.util.function.BiConsumer;
+
+import com.typesafe.config.Config;
+import io.jooby.SneakyThrows;
+import io.vertx.core.AsyncResult;
+import io.vertx.core.CompositeFuture;
+import io.vertx.core.Future;
+import io.vertx.core.Handler;
+import io.vertx.core.Vertx;
+import io.vertx.core.VertxOptions;
+import io.vertx.pgclient.PgConnectOptions;
+import io.vertx.pgclient.PgConnection;
+import io.vertx.sqlclient.PreparedQuery;
+import io.vertx.sqlclient.PreparedStatement;
+import io.vertx.sqlclient.Row;
+import io.vertx.sqlclient.RowSet;
+import io.vertx.sqlclient.Tuple;
+import io.vertx.sqlclient.impl.SqlClientInternal;
+
+public class PgClient {
+  private static final String UPDATE_WORLD = "UPDATE world SET randomnumber=$1 WHERE id=$2";
+  private static final String SELECT_WORLD = "SELECT id, randomnumber from WORLD where id=$1";
+  private static final String SELECT_FORTUNE = "SELECT id, message from FORTUNE";
+  private SqlClientInternal client;
+  private PreparedQuery<RowSet<Row>> SELECT_WORLD_QUERY;
+  private PreparedQuery<RowSet<Row>> SELECT_FORTUNE_QUERY;
+  private PreparedQuery<RowSet<Row>> UPDATE_WORLD_QUERY;
+
+  public PgClient(Config config) {
+    try {
+      Vertx vertx = Vertx.vertx(
+          new VertxOptions().setPreferNativeTransport(true).setWorkerPoolSize(4));
+      PgConnectOptions connectOptions = pgPoolOptions(config);
+
+      Future future = PgConnection.connect(vertx, connectOptions)
+          .flatMap(conn -> {
+            client = (SqlClientInternal) conn;
+            Future<PreparedStatement> f1 = conn.prepare(SELECT_WORLD);
+            Future<PreparedStatement> f2 = conn.prepare(SELECT_FORTUNE);
+            Future<PreparedStatement> f3 = conn.prepare(UPDATE_WORLD);
+            f1.onSuccess(ps -> SELECT_WORLD_QUERY = ps.query());
+            f2.onSuccess(ps -> SELECT_FORTUNE_QUERY = ps.query());
+            f3.onSuccess(ps -> UPDATE_WORLD_QUERY = ps.query());
+            return Future.all(f1, f2, f3);
+          })
+          .toCompletionStage()
+          .toCompletableFuture()
+          .get();
+      Throwable cause = future.cause();
+      if (cause != null) {
+        throw SneakyThrows.propagate(cause);
+      }
+    } catch (InterruptedException | ExecutionException cause) {
+      throw SneakyThrows.propagate(cause);
+    }
+  }
+
+  public void selectWorld(Tuple row, Handler<AsyncResult<RowSet<Row>>> handler) {
+    SELECT_WORLD_QUERY.execute(row, handler);
+  }
+
+  public void selectWorldQuery(int queries,
+      BiConsumer<Integer, PreparedQuery<RowSet<Row>>> consumer) {
+    client.group(c -> {
+      for (int i = 0; i < queries; i++) {
+        consumer.accept(i, c.preparedQuery(SELECT_WORLD));
+      }
+    });
+  }
+
+  public PreparedQuery<RowSet<Row>> fortuneQuery() {
+    return SELECT_FORTUNE_QUERY;
+  }
+
+  public void selectWorldForUpdate(int queries,
+      BiConsumer<Integer, PreparedQuery<RowSet<Row>>> consumer) {
+    client.group(c -> {
+      PreparedQuery<RowSet<Row>> statement = c.preparedQuery(SELECT_WORLD);
+      for (int i = 0; i < queries; i++) {
+        consumer.accept(i, statement);
+      }
+    });
+  }
+
+  public void updateWorld(List<Tuple> batch, Handler<AsyncResult<RowSet<Row>>> handler) {
+    UPDATE_WORLD_QUERY.executeBatch(batch, handler);
+  }
+
+  private PgConnectOptions pgPoolOptions(Config config) {
+    PgConnectOptions options = new PgConnectOptions();
+    options.setDatabase(config.getString("databaseName"));
+    options.setHost(config.getString("serverName"));
+    options.setPort(config.getInt("portNumber"));
+    options.setUser(config.getString("user"));
+    options.setPassword(config.getString("password"));
+    options.setCachePreparedStatements(true);
+    // Large pipelining means less flushing and we use a single connection anyway
+    options.setPipeliningLimit(100_000);
+    return options;
+  }
+}

+ 0 - 42
frameworks/Java/jooby/src/main/java/com/techempower/PgClients.java

@@ -1,42 +0,0 @@
-package com.techempower;
-
-import com.typesafe.config.Config;
-import io.vertx.core.Vertx;
-import io.vertx.core.VertxOptions;
-import io.vertx.pgclient.PgConnectOptions;
-import io.vertx.pgclient.PgPool;
-import io.vertx.sqlclient.PoolOptions;
-
-public class PgClients {
-  private static final PoolOptions SINGLE = new PoolOptions().setMaxSize(1);
-
-  private final PgConnectOptions connectOptions;
-
-  private final Vertx vertx;
-
-  private ThreadLocal<PgPool> sqlClient = ThreadLocal.withInitial(this::sqlClientPool);
-
-  public PgClients(Config config) {
-    this.vertx = Vertx.vertx(new VertxOptions().setPreferNativeTransport(true).setWorkerPoolSize(4));
-    this.connectOptions = pgPoolOptions(config);
-  }
-
-  public PgPool next() {
-    return sqlClient.get();
-  }
-
-  private PgConnectOptions pgPoolOptions(Config config) {
-    PgConnectOptions options = new PgConnectOptions();
-    options.setDatabase(config.getString("databaseName"));
-    options.setHost(config.getString("serverName"));
-    options.setPort(config.getInt("portNumber"));
-    options.setUser(config.getString("user"));
-    options.setPassword(config.getString("password"));
-    options.setCachePreparedStatements(true);
-    return options;
-  }
-
-  private PgPool sqlClientPool() {
-    return PgPool.pool(vertx, connectOptions, SINGLE);
-  }
-}

+ 39 - 59
frameworks/Java/jooby/src/main/java/com/techempower/ReactivePg.java

@@ -4,7 +4,6 @@ import static com.techempower.Util.randomWorld;
 import static io.jooby.ExecutionMode.EVENT_LOOP;
 import static io.jooby.ExecutionMode.EVENT_LOOP;
 import static io.jooby.MediaType.JSON;
 import static io.jooby.MediaType.JSON;
 
 
-import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Collections;
@@ -18,18 +17,12 @@ import io.jooby.MediaType;
 import io.jooby.ServerOptions;
 import io.jooby.ServerOptions;
 import io.jooby.rocker.ByteBufferOutput;
 import io.jooby.rocker.ByteBufferOutput;
 import io.jooby.rocker.RockerModule;
 import io.jooby.rocker.RockerModule;
-import io.vertx.pgclient.PgPool;
 import io.vertx.sqlclient.Row;
 import io.vertx.sqlclient.Row;
 import io.vertx.sqlclient.RowIterator;
 import io.vertx.sqlclient.RowIterator;
-import io.vertx.sqlclient.SqlConnection;
 import io.vertx.sqlclient.Tuple;
 import io.vertx.sqlclient.Tuple;
 
 
 public class ReactivePg extends Jooby {
 public class ReactivePg extends Jooby {
 
 
-  private static final String UPDATE_WORLD = "UPDATE world SET randomnumber=$1 WHERE id=$2";
-  private static final String SELECT_WORLD = "SELECT id, randomnumber from WORLD where id=$1";
-  private static final String SELECT_FORTUNE = "SELECT id, message from FORTUNE";
-
   {
   {
     /** Reduce the number of resources due we do reactive processing. */
     /** Reduce the number of resources due we do reactive processing. */
     setServerOptions(
     setServerOptions(
@@ -39,14 +32,14 @@ public class ReactivePg extends Jooby {
     );
     );
 
 
     /** PG client: */
     /** PG client: */
-    PgClients clients = new PgClients(getConfig().getConfig("db"));
+    PgClient client = new PgClient(getConfig().getConfig("db"));
 
 
     /** Template engine: */
     /** Template engine: */
     install(new RockerModule().reuseBuffer(true));
     install(new RockerModule().reuseBuffer(true));
 
 
     /** Single query: */
     /** Single query: */
     get("/db", ctx -> {
     get("/db", ctx -> {
-      clients.next().preparedQuery(SELECT_WORLD).execute(Tuple.of(randomWorld()), rsp -> {
+      client.selectWorld(Tuple.of(randomWorld()), rsp -> {
         if (rsp.succeeded()) {
         if (rsp.succeeded()) {
           RowIterator<Row> rs = rsp.result().iterator();
           RowIterator<Row> rs = rsp.result().iterator();
           Row row = rs.next();
           Row row = rs.next();
@@ -57,84 +50,71 @@ public class ReactivePg extends Jooby {
         }
         }
       });
       });
       return ctx;
       return ctx;
-    });
+    }).setNonBlocking(true);
 
 
     /** Multiple queries: */
     /** Multiple queries: */
     get("/queries", ctx -> {
     get("/queries", ctx -> {
       int queries = Util.queries(ctx);
       int queries = Util.queries(ctx);
-      AtomicInteger counter = new AtomicInteger();
       World[] result = new World[queries];
       World[] result = new World[queries];
-      PgPool client = clients.next();
-      for (int i = 0; i < result.length; i++) {
-        client.preparedQuery(SELECT_WORLD).execute(Tuple.of(randomWorld()), rsp -> {
+      client.selectWorldQuery(queries, (index, statement) -> {
+        statement.execute(Tuple.of(randomWorld()), rsp -> {
           if (rsp.succeeded()) {
           if (rsp.succeeded()) {
             RowIterator<Row> rs = rsp.result().iterator();
             RowIterator<Row> rs = rsp.result().iterator();
             Row row = rs.next();
             Row row = rs.next();
-            result[counter.get()] = new World(row.getInteger(0), row.getInteger(1));
+            result[index] = new World(row.getInteger(0), row.getInteger(1));
           } else {
           } else {
             sendError(ctx, rsp.cause());
             sendError(ctx, rsp.cause());
           }
           }
           // ready?
           // ready?
-          if (counter.incrementAndGet() == queries) {
+          if (index == queries - 1) {
             ctx.setResponseType(JSON)
             ctx.setResponseType(JSON)
                 .send(Json.encode(result));
                 .send(Json.encode(result));
           }
           }
         });
         });
-      }
+      });
       return ctx;
       return ctx;
-    });
+    }).setNonBlocking(true);
 
 
     /** Update queries: */
     /** Update queries: */
     get("/updates", ctx -> {
     get("/updates", ctx -> {
       int queries = Util.queries(ctx);
       int queries = Util.queries(ctx);
       World[] result = new World[queries];
       World[] result = new World[queries];
-      AtomicInteger counter = new AtomicInteger(0);
-      PgPool pool = clients.next();
-      pool.getConnection(connectCallback -> {
-        if (connectCallback.failed()) {
-          sendError(ctx, connectCallback.cause());
-          return;
-        }
-        SqlConnection conn = connectCallback.result();
-        for (int i = 0; i < queries; i++) {
-          int id = randomWorld();
-          conn.preparedQuery(SELECT_WORLD).execute(Tuple.of(id), selectCallback -> {
-            if (selectCallback.failed()) {
-              conn.close();
-              sendError(ctx, selectCallback.cause());
-              return;
+      client.selectWorldForUpdate(queries, (index, statement) -> {
+        int id = randomWorld();
+        statement.execute(Tuple.of(id), selectCallback -> {
+          if (selectCallback.failed()) {
+            sendError(ctx, selectCallback.cause());
+            return;
+          }
+          result[index] = new World(
+              selectCallback.result().iterator().next().getInteger(0),
+              randomWorld());
+          if (index == queries - 1) {
+            // Sort results... avoid dead locks
+            Arrays.sort(result);
+            List<Tuple> batch = new ArrayList<>(queries);
+            for (World world : result) {
+              batch.add(Tuple.of(world.getRandomNumber(), world.getId()));
             }
             }
-            result[counter.get()] = new World(
-                selectCallback.result().iterator().next().getInteger(0),
-                randomWorld());
-            if (counter.incrementAndGet() == queries) {
-              // Sort results... avoid dead locks
-              Arrays.sort(result);
-              List<Tuple> batch = new ArrayList<>(queries);
-              for (World world : result) {
-                batch.add(Tuple.of(world.getRandomNumber(), world.getId()));
-              }
 
 
-              conn.preparedQuery(UPDATE_WORLD).executeBatch(batch, updateCallback -> {
-                if (updateCallback.failed()) {
-                  sendError(ctx, updateCallback.cause());
-                } else {
-                  ctx.setResponseType(JSON)
-                      .send(Json.encode(result));
-                }
-                conn.close();
-              });
-            }
-          });
-        }
+            client.updateWorld(batch, updateCallback -> {
+              if (updateCallback.failed()) {
+                sendError(ctx, updateCallback.cause());
+              } else {
+                ctx.setResponseType(JSON)
+                    .send(Json.encode(result));
+              }
+            });
+          }
+        });
       });
       });
       return ctx;
       return ctx;
-    });
+    }).setNonBlocking(true);
 
 
     /** Fortunes: */
     /** Fortunes: */
     RockerOutputFactory<ByteBufferOutput> factory = require(RockerOutputFactory.class);
     RockerOutputFactory<ByteBufferOutput> factory = require(RockerOutputFactory.class);
     get("/fortunes", ctx -> {
     get("/fortunes", ctx -> {
-      clients.next().preparedQuery(SELECT_FORTUNE).execute(rsp -> {
+      client.fortuneQuery().execute(rsp -> {
         if (rsp.succeeded()) {
         if (rsp.succeeded()) {
           RowIterator<Row> rs = rsp.result().iterator();
           RowIterator<Row> rs = rsp.result().iterator();
           List<Fortune> fortunes = new ArrayList<>();
           List<Fortune> fortunes = new ArrayList<>();
@@ -152,11 +132,11 @@ public class ReactivePg extends Jooby {
           ctx.setResponseType(MediaType.html)
           ctx.setResponseType(MediaType.html)
               .send(template.render(factory).toBuffer());
               .send(template.render(factory).toBuffer());
         } else {
         } else {
-          ctx.sendError(rsp.cause());
+          sendError(ctx, rsp.cause());
         }
         }
       });
       });
       return ctx;
       return ctx;
-    });
+    }).setNonBlocking(true);
   }
   }
 
 
   private void sendError(Context ctx, Throwable cause) {
   private void sendError(Context ctx, Throwable cause) {

+ 4 - 4
frameworks/Java/jooby/src/main/java/com/techempower/Resource.java

@@ -1,12 +1,12 @@
 package com.techempower;
 package com.techempower;
 
 
 import io.jooby.Context;
 import io.jooby.Context;
-import io.jooby.annotations.Dispatch;
+import io.jooby.annotation.GET;
+import io.jooby.annotation.Path;
+import io.jooby.annotation.Dispatch;
 import views.fortunes;
 import views.fortunes;
 
 
 import javax.sql.DataSource;
 import javax.sql.DataSource;
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
 import java.io.IOException;
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
 import java.nio.charset.StandardCharsets;
 import java.sql.Connection;
 import java.sql.Connection;
@@ -117,7 +117,7 @@ public class Resource {
 
 
   @GET @Path("/fortunes")
   @GET @Path("/fortunes")
   @Dispatch
   @Dispatch
-  public fortunes fortunes(Context ctx) throws Exception {
+  public fortunes fortunes() throws Exception {
     List<Fortune> fortunes = new ArrayList<>();
     List<Fortune> fortunes = new ArrayList<>();
     try (Connection connection = dataSource.getConnection()) {
     try (Connection connection = dataSource.getConnection()) {
       try (PreparedStatement stt = connection.prepareStatement("select * from fortune")) {
       try (PreparedStatement stt = connection.prepareStatement("select * from fortune")) {

+ 3 - 7
frameworks/Kotlin/kooby/kooby.dockerfile

@@ -1,15 +1,11 @@
-FROM maven:3.6.1-jdk-11-slim as maven
+FROM maven:3.9.0-eclipse-temurin-17
 WORKDIR /kooby
 WORKDIR /kooby
 COPY pom.xml pom.xml
 COPY pom.xml pom.xml
 COPY src src
 COPY src src
 COPY public public
 COPY public public
-RUN mvn package -q
-
-FROM openjdk:11.0.3-jdk-slim
-WORKDIR /kooby
-COPY --from=maven /kooby/target/kooby.jar app.jar
 COPY conf conf
 COPY conf conf
+RUN mvn package -q
 
 
 EXPOSE 8080
 EXPOSE 8080
 
 
-CMD ["java", "-server", "-Xms4g", "-Xmx4g", "-XX:+AggressiveOpts", "-XX:-UseBiasedLocking", "-XX:+UseStringDeduplication", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-jar", "app.jar"]
+CMD ["java", "-server", "-Xms2g", "-Xmx2g", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-jar", "target/kooby.jar"]

+ 19 - 24
frameworks/Kotlin/kooby/pom.xml

@@ -7,23 +7,28 @@
 
 
   <artifactId>kooby</artifactId>
   <artifactId>kooby</artifactId>
   <groupId>com.techempower</groupId>
   <groupId>com.techempower</groupId>
-  <version>2.0</version>
+  <version>3.0</version>
 
 
   <name>kooby: jooby+kotlin</name>
   <name>kooby: jooby+kotlin</name>
 
 
   <properties>
   <properties>
-    <jooby.version>2.9.5</jooby.version>
-    <postgresql.version>42.4.3</postgresql.version>
+    <jooby.version>3.0.0</jooby.version>
+    <postgresql.version>42.6.0</postgresql.version>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-    <maven.compiler.source>11</maven.compiler.source>
-    <maven.compiler.target>11</maven.compiler.target>
+    <maven.compiler.source>17</maven.compiler.source>
+    <maven.compiler.target>17</maven.compiler.target>
+    <kotlin.version>1.8.21</kotlin.version>
 
 
     <!-- Startup class -->
     <!-- Startup class -->
     <application.class>kooby.AppKt</application.class>
     <application.class>kooby.AppKt</application.class>
-    <kotlin.version>1.3.72</kotlin.version>
   </properties>
   </properties>
 
 
   <dependencies>
   <dependencies>
+    <dependency>
+      <groupId>io.jooby</groupId>
+      <artifactId>jooby-kotlin</artifactId>
+    </dependency>
+
     <!-- jackson -->
     <!-- jackson -->
     <dependency>
     <dependency>
       <groupId>io.jooby</groupId>
       <groupId>io.jooby</groupId>
@@ -42,10 +47,12 @@
       <artifactId>jooby-rocker</artifactId>
       <artifactId>jooby-rocker</artifactId>
     </dependency>
     </dependency>
 
 
+    <!-- mySQL -->
     <!-- mySQL -->
     <!-- mySQL -->
     <dependency>
     <dependency>
-      <groupId>mysql</groupId>
-      <artifactId>mysql-connector-java</artifactId>
+      <groupId>com.mysql</groupId>
+      <artifactId>mysql-connector-j</artifactId>
+      <version>8.0.33</version>
     </dependency>
     </dependency>
 
 
     <!-- postgresql -->
     <!-- postgresql -->
@@ -55,23 +62,11 @@
       <version>${postgresql.version}</version>
       <version>${postgresql.version}</version>
     </dependency>
     </dependency>
 
 
-    <!-- logging -->
-    <dependency>
-      <groupId>ch.qos.logback</groupId>
-      <artifactId>logback-classic</artifactId>
-    </dependency>
-
     <dependency>
     <dependency>
       <groupId>io.jooby</groupId>
       <groupId>io.jooby</groupId>
-      <artifactId>jooby-utow</artifactId>
-      <version>${jooby.version}</version>
+      <artifactId>jooby-undertow</artifactId>
     </dependency>
     </dependency>
 
 
-    <dependency>
-      <groupId>org.jetbrains.kotlin</groupId>
-      <artifactId>kotlin-stdlib-jdk8</artifactId>
-      <version>${kotlin.version}</version>
-    </dependency>
   </dependencies>
   </dependencies>
 
 
   <build>
   <build>
@@ -99,12 +94,12 @@
         </executions>
         </executions>
       </plugin>
       </plugin>
       <plugin>
       <plugin>
+        <groupId>org.jetbrains.kotlin</groupId>
         <artifactId>kotlin-maven-plugin</artifactId>
         <artifactId>kotlin-maven-plugin</artifactId>
         <version>${kotlin.version}</version>
         <version>${kotlin.version}</version>
         <configuration>
         <configuration>
-          <jvmTarget>1.8</jvmTarget>
+          <jvmTarget>17</jvmTarget>
         </configuration>
         </configuration>
-        <groupId>org.jetbrains.kotlin</groupId>
         <executions>
         <executions>
           <execution>
           <execution>
             <id>compile</id>
             <id>compile</id>
@@ -132,7 +127,7 @@
       <plugin>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-compiler-plugin</artifactId>
         <artifactId>maven-compiler-plugin</artifactId>
-        <version>3.8.1</version>
+        <version>3.11.0</version>
         <executions>
         <executions>
           <!-- Replacing default-compile as it is treated specially by maven -->
           <!-- Replacing default-compile as it is treated specially by maven -->
           <execution>
           <execution>

+ 6 - 6
frameworks/Kotlin/kooby/src/main/kotlin/kooby/App.kt

@@ -6,10 +6,10 @@ import io.jooby.Context
 import io.jooby.ExecutionMode.EVENT_LOOP
 import io.jooby.ExecutionMode.EVENT_LOOP
 import io.jooby.MediaType.JSON
 import io.jooby.MediaType.JSON
 import io.jooby.hikari.HikariModule
 import io.jooby.hikari.HikariModule
-import io.jooby.json.JacksonModule
-import io.jooby.require
+import io.jooby.jackson.JacksonModule
+import io.jooby.kt.require
 import io.jooby.rocker.RockerModule
 import io.jooby.rocker.RockerModule
-import io.jooby.runApp
+import io.jooby.kt.runApp
 import java.util.*
 import java.util.*
 import java.util.concurrent.ThreadLocalRandom
 import java.util.concurrent.ThreadLocalRandom
 import javax.sql.DataSource
 import javax.sql.DataSource
@@ -32,6 +32,9 @@ data class Fortune(val id: Int, var message: String)
 fun main(args: Array<String>) {
 fun main(args: Array<String>) {
   runApp(args, EVENT_LOOP) {
   runApp(args, EVENT_LOOP) {
 
 
+    /** Template engine: */
+    install(RockerModule().reuseBuffer(true))
+
     /** JSON: */
     /** JSON: */
     install(JacksonModule())
     install(JacksonModule())
     val mapper = require(ObjectMapper::class)
     val mapper = require(ObjectMapper::class)
@@ -40,9 +43,6 @@ fun main(args: Array<String>) {
     install(HikariModule())
     install(HikariModule())
     val ds = require(DataSource::class)
     val ds = require(DataSource::class)
 
 
-    /** Template engine: */
-    install(RockerModule().reuseBuffer(true))
-
     get("/plaintext") {
     get("/plaintext") {
       ctx.send(MESSAGE_BYTES)
       ctx.send(MESSAGE_BYTES)
     }
     }