Browse Source

Use Quarkus Beta, Added RESTEasy Reactive and Hibernate Reactive options (#6224)

Stéphane Épardaud 4 years ago
parent
commit
c39ce85130
100 changed files with 2574 additions and 248 deletions
  1. 8 13
      frameworks/Java/quarkus/README.md
  2. 0 40
      frameworks/Java/quarkus/base/pom.xml
  3. 97 5
      frameworks/Java/quarkus/benchmark_config.json
  4. 0 45
      frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/resource/pgclient/FortuneResource.java
  5. 0 21
      frameworks/Java/quarkus/pgclient/src/main/resources/templates/Fortunes.rocker.html
  6. 27 23
      frameworks/Java/quarkus/pom.xml
  7. 28 0
      frameworks/Java/quarkus/quarkus-reactive-routes-hibernate-reactive.dockerfile
  8. 20 10
      frameworks/Java/quarkus/quarkus-reactive-routes-pgclient.dockerfile
  9. 28 0
      frameworks/Java/quarkus/quarkus-resteasy-reactive-hibernate-reactive.dockerfile
  10. 28 0
      frameworks/Java/quarkus/quarkus-resteasy-reactive-hibernate.dockerfile
  11. 28 0
      frameworks/Java/quarkus/quarkus-resteasy-reactive-pgclient.dockerfile
  12. 20 10
      frameworks/Java/quarkus/quarkus.dockerfile
  13. 46 0
      frameworks/Java/quarkus/reactive-routes-hibernate-reactive/pom.xml
  14. 1 1
      frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/filter/ServerHeaderFilter.java
  15. 1 1
      frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/model/Fortune.java
  16. 1 1
      frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/model/World.java
  17. 19 0
      frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/repository/BaseRepository.java
  18. 25 0
      frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/repository/FortuneRepository.java
  19. 65 0
      frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/repository/WorldRepository.java
  20. 34 0
      frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/resource/BaseResource.java
  21. 130 0
      frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/resource/DbResource.java
  22. 47 0
      frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/resource/FortuneResource.java
  23. 21 0
      frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/resource/JsonResource.java
  24. 2 3
      frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/resource/PlaintextResource.java
  25. 20 0
      frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/resources/application.properties
  26. 0 0
      frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/resources/fortunes.mustache
  27. 0 0
      frameworks/Java/quarkus/reactive-routes-hibernate-reactive/start-app.sh
  28. 8 26
      frameworks/Java/quarkus/reactive-routes-pgclient/pom.xml
  29. 33 0
      frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/filter/ServerHeaderFilter.java
  30. 0 0
      frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/model/Fortune.java
  31. 0 0
      frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/model/World.java
  32. 1 1
      frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/repository/FortuneRepository.java
  33. 1 1
      frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/repository/PgClientFactory.java
  34. 1 1
      frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/repository/PgClients.java
  35. 1 1
      frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/repository/WorldRepository.java
  36. 1 1
      frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/resource/BaseResource.java
  37. 4 4
      frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/resource/DbResource.java
  38. 49 0
      frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/resource/FortuneResource.java
  39. 1 1
      frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/resource/JsonResource.java
  40. 1 1
      frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/resource/Message.java
  41. 23 0
      frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/resource/PlaintextResource.java
  42. 1 1
      frameworks/Java/quarkus/reactive-routes-pgclient/src/main/resources/application.properties
  43. 20 0
      frameworks/Java/quarkus/reactive-routes-pgclient/src/main/resources/fortunes.mustache
  44. 2 0
      frameworks/Java/quarkus/reactive-routes-pgclient/start-app.sh
  45. 0 0
      frameworks/Java/quarkus/resteasy-hibernate/README.md
  46. 16 4
      frameworks/Java/quarkus/resteasy-hibernate/pom.xml
  47. 3 0
      frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/cdi/HibernateOrmNativeComponents.java
  48. 0 0
      frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/filter/ServerHeaderFilter.java
  49. 56 0
      frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/model/Fortune.java
  50. 29 0
      frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/model/World.java
  51. 9 7
      frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/repository/FortuneRepository.java
  52. 5 3
      frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/repository/WorldRepository.java
  53. 5 4
      frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/resource/DbResource.java
  54. 7 6
      frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/resource/FortuneResource.java
  55. 2 5
      frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/resource/JsonResource.java
  56. 13 0
      frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/resource/Message.java
  57. 0 0
      frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/resource/PlaintextResource.java
  58. 9 8
      frameworks/Java/quarkus/resteasy-hibernate/src/main/resources/application.properties
  59. 20 0
      frameworks/Java/quarkus/resteasy-hibernate/src/main/resources/fortunes.mustache
  60. 0 0
      frameworks/Java/quarkus/resteasy-hibernate/src/main/resources/import.sql
  61. 0 0
      frameworks/Java/quarkus/resteasy-hibernate/start-app.sh
  62. 51 0
      frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/pom.xml
  63. 33 0
      frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/filter/ServerHeaderFilter.java
  64. 56 0
      frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/model/Fortune.java
  65. 29 0
      frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/model/World.java
  66. 19 0
      frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/repository/BaseRepository.java
  67. 25 0
      frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/repository/FortuneRepository.java
  68. 65 0
      frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/repository/WorldRepository.java
  69. 117 0
      frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/resource/DbResource.java
  70. 47 0
      frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/resource/FortuneResource.java
  71. 19 0
      frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/resource/JsonResource.java
  72. 13 0
      frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/resource/Message.java
  73. 20 0
      frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/resource/PlaintextResource.java
  74. 20 0
      frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/resources/application.properties
  75. 20 0
      frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/resources/fortunes.mustache
  76. 2 0
      frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/start-app.sh
  77. 69 0
      frameworks/Java/quarkus/resteasy-reactive-hibernate/README.md
  78. 44 0
      frameworks/Java/quarkus/resteasy-reactive-hibernate/pom.xml
  79. 24 0
      frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/cdi/HibernateOrmNativeComponents.java
  80. 32 0
      frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/filter/ServerHeaderFilter.java
  81. 56 0
      frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/model/Fortune.java
  82. 29 0
      frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/model/World.java
  83. 31 0
      frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/repository/FortuneRepository.java
  84. 77 0
      frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/repository/WorldRepository.java
  85. 137 0
      frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/resource/DbResource.java
  86. 56 0
      frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/resource/FortuneResource.java
  87. 18 0
      frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/resource/JsonResource.java
  88. 13 0
      frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/resource/Message.java
  89. 17 0
      frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/resource/PlaintextResource.java
  90. 30 0
      frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/resources/application.properties
  91. 20 0
      frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/resources/fortunes.mustache
  92. 1 0
      frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/resources/import.sql
  93. 1 0
      frameworks/Java/quarkus/resteasy-reactive-hibernate/start-app.sh
  94. 117 0
      frameworks/Java/quarkus/resteasy-reactive-pgclient/.factorypath
  95. 47 0
      frameworks/Java/quarkus/resteasy-reactive-pgclient/pom.xml
  96. 33 0
      frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/java/io/quarkus/benchmark/filter/ServerHeaderFilter.java
  97. 48 0
      frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/java/io/quarkus/benchmark/model/Fortune.java
  98. 35 0
      frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/java/io/quarkus/benchmark/model/World.java
  99. 30 0
      frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/java/io/quarkus/benchmark/repository/FortuneRepository.java
  100. 56 0
      frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/java/io/quarkus/benchmark/repository/PgClientFactory.java

+ 8 - 13
frameworks/Java/quarkus/README.md

@@ -4,24 +4,19 @@ This is the Quarkus portion of a [benchmarking test suite](../) comparing a vari
 
 
 ## Implementations
 ## Implementations
 
 
-There are currently two repository implementations.
+There are currently 6 repository implementations:
 
 
-### JAX-RS and Hibernate via JPA
-* [Plaintext test source](hibernate/src/main/java/io/quarkus/benchmark/resource/PlaintextResource.java)
-* [JSON test source](hibernate/src/main/java/io/quarkus/benchmark/resource/JsonResource.java)
-* [Query, Queries, Update test source](hibernate/src/main/java/io/quarkus/benchmark/repository/hibernate/WorldRepository.java)
-* [Fortunes test source](hibernate/src/main/java/io/quarkus/benchmark/repository/hibernate/FortuneRepository.java)
-
-### Reactive Routes and Asynchronous DB accesses via pgclient
-* [Plaintext test source](pgclient/src/main/java/io/quarkus/benchmark/resource/pgclient/PlaintextResource.java)
-* [JSON test source](pgclient/src/main/java/io/quarkus/benchmark/resource/pgclient/JsonResource.java)
-* [Query, Queries, Update test source](pgclient/src/main/java/io/quarkus/benchmark/repository/pgclient/WorldRepository.java)
-* [Fortunes test source](pgclient/src/main/java/io/quarkus/benchmark/repository/pgclient/FortuneRepository.java)
+- RESTEasy and Hibernate ORM
+- RESTEasy Reactive and Hibernate ORM
+- RESTEasy Reactive and Hibernate Reactive
+- RESTEasy Reactive and Vert.x PG Client
+- Reactive Routes and Hibernate Reactive
+- Reactive Routes and Vert.x PG Client
 
 
 ## Versions
 ## Versions
 
 
 * [Java OpenJDK 11](http://openjdk.java.net/)
 * [Java OpenJDK 11](http://openjdk.java.net/)
-* [Quarkus 1.1.1](https://quarkus.io)
+* [Quarkus 1.11.0.Beta1](https://quarkus.io)
 
 
 ## Test URLs
 ## Test URLs
 
 

+ 0 - 40
frameworks/Java/quarkus/base/pom.xml

@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project>
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <groupId>io.quarkus</groupId>
-        <artifactId>benchmark</artifactId>
-        <version>1.0-SNAPSHOT</version>
-        <relativePath>../</relativePath>
-    </parent>
-
-    <groupId>io.quarkus.benchmark</groupId>
-    <artifactId>base</artifactId>
-
-    <dependencies>
-        <dependency>
-            <groupId>io.quarkus</groupId>
-            <artifactId>quarkus-scheduler</artifactId>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.jboss.jandex</groupId>
-                <artifactId>jandex-maven-plugin</artifactId>
-                <version>1.0.7</version>
-                <executions>
-                    <execution>
-                        <id>make-index</id>
-                        <goals>
-                            <goal>jandex</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>

+ 97 - 5
frameworks/Java/quarkus/benchmark_config.json

@@ -21,11 +21,34 @@
         "webserver": "Undertow",
         "webserver": "Undertow",
         "os": "Linux",
         "os": "Linux",
         "database_os": "Linux",
         "database_os": "Linux",
-        "display_name": "Quarkus + Hibernate ORM",
+        "display_name": "Quarkus + RESTEasy + Hibernate ORM",
         "notes": "",
         "notes": "",
         "versus": "Netty"
         "versus": "Netty"
       },
       },
-      "pgclient": {
+      "reactive-routes-hibernate-reactive": {
+        "json_url": "/json",
+        "db_url": "/db",
+        "query_url": "/queries?queries=",
+        "update_url": "/updates?queries=",
+        "fortune_url": "/fortunes",
+        "plaintext_url": "/plaintext",
+        "port": 8080,
+        "approach": "Realistic",
+        "classification": "fullstack",
+        "database": "Postgres",
+        "framework": "Quarkus",
+        "language": "Java",
+        "flavor": "None",
+        "orm": "Full",
+        "platform": "Vertx-Web",
+        "webserver": "Vertx",
+        "os": "Linux",
+        "database_os": "Linux",
+        "display_name": "Quarkus + Reactive Routes + Hibernate Reactive",
+        "notes": "",
+        "versus": "Netty"
+      },
+      "reactive-routes-pgclient": {
         "json_url": "/json",
         "json_url": "/json",
         "db_url": "/db",
         "db_url": "/db",
         "query_url": "/queries?queries=",
         "query_url": "/queries?queries=",
@@ -40,11 +63,80 @@
         "language": "Java",
         "language": "Java",
         "flavor": "None",
         "flavor": "None",
         "orm": "Micro",
         "orm": "Micro",
-        "platform": "JAX-RS",
-        "webserver": "Undertow",
+        "platform": "Vertx-Web",
+        "webserver": "Vertx",
+        "os": "Linux",
+        "database_os": "Linux",
+        "display_name": "Quarkus + Reactive Routes + PgClient",
+        "notes": "",
+        "versus": "Netty"
+      },
+      "resteasy-reactive-pgclient": {
+        "json_url": "/json",
+        "db_url": "/db",
+        "query_url": "/queries?queries=",
+        "update_url": "/updates?queries=",
+        "fortune_url": "/fortunes",
+        "plaintext_url": "/plaintext",
+        "port": 8080,
+        "approach": "Realistic",
+        "classification": "fullstack",
+        "database": "Postgres",
+        "framework": "Quarkus",
+        "language": "Java",
+        "flavor": "None",
+        "orm": "Micro",
+        "platform": "RESTEasy Reactive",
+        "webserver": "Vertx",
+        "os": "Linux",
+        "database_os": "Linux",
+        "display_name": "Quarkus RESTEasy Reactive + PgClient",
+        "notes": "",
+        "versus": "Netty"
+      },
+      "resteasy-reactive-hibernate": {
+        "json_url": "/json",
+        "db_url": "/db",
+        "query_url": "/queries?queries=",
+        "update_url": "/updates?queries=",
+        "fortune_url": "/fortunes",
+        "plaintext_url": "/plaintext",
+        "port": 8080,
+        "approach": "Realistic",
+        "classification": "fullstack",
+        "database": "Postgres",
+        "framework": "Quarkus",
+        "language": "Java",
+        "flavor": "None",
+        "orm": "Micro",
+        "platform": "RESTEasy Reactive",
+        "webserver": "Vertx",
+        "os": "Linux",
+        "database_os": "Linux",
+        "display_name": "Quarkus RESTEasy Reactive + Hibernate",
+        "notes": "",
+        "versus": "Netty"
+      },
+      "resteasy-reactive-hibernate-reactive": {
+        "json_url": "/json",
+        "db_url": "/db",
+        "query_url": "/queries?queries=",
+        "update_url": "/updates?queries=",
+        "fortune_url": "/fortunes",
+        "plaintext_url": "/plaintext",
+        "port": 8080,
+        "approach": "Realistic",
+        "classification": "fullstack",
+        "database": "Postgres",
+        "framework": "Quarkus",
+        "language": "Java",
+        "flavor": "None",
+        "orm": "Micro",
+        "platform": "RESTEasy Reactive",
+        "webserver": "Vertx",
         "os": "Linux",
         "os": "Linux",
         "database_os": "Linux",
         "database_os": "Linux",
-        "display_name": "quarkus-pgclient",
+        "display_name": "Quarkus RESTEasy Reactive + Hibernate Reactive",
         "notes": "",
         "notes": "",
         "versus": "Netty"
         "versus": "Netty"
       }
       }

+ 0 - 45
frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/resource/pgclient/FortuneResource.java

@@ -1,45 +0,0 @@
-package io.quarkus.benchmark.resource.pgclient;
-
-import io.quarkus.benchmark.model.Fortune;
-import io.quarkus.benchmark.repository.pgclient.FortuneRepository;
-import io.quarkus.vertx.web.Route;
-import io.vertx.core.http.HttpHeaders;
-import io.vertx.ext.web.RoutingContext;
-import io.vertx.reactivex.ext.web.templ.rocker.RockerTemplateEngine;
-
-import javax.enterprise.context.ApplicationScoped;
-import javax.inject.Inject;
-import java.util.Comparator;
-
-@ApplicationScoped
-public class FortuneResource extends BaseResource {
-
-    @Inject
-    FortuneRepository repository;
-
-    private final RockerTemplateEngine templeEngine;
-
-    public FortuneResource() {
-        templeEngine = RockerTemplateEngine.create();
-    }
-
-    @Route(path = "fortunes")
-    public void fortunes(RoutingContext rc) {
-        repository.findAll()
-                .subscribe().with(fortunes -> {
-                    fortunes.add(new Fortune(0, "Additional fortune added at request time."));
-                    fortunes.sort(Comparator.comparing(fortune -> fortune.getMessage()));
-                    rc.put("fortunes", fortunes);
-                    templeEngine.render(rc.data(), "templates/Fortunes.rocker.html", res -> {
-                        if (res.succeeded()) {
-                            rc.response()
-                                    .putHeader(HttpHeaders.CONTENT_TYPE, "text/html; charset=UTF-8")
-                                    .end(res.result().toString());
-                        } else {
-                            rc.fail(res.cause());
-                        }
-                    });
-                },
-                t -> handleFail(rc, t));
-    }
-}

+ 0 - 21
frameworks/Java/quarkus/pgclient/src/main/resources/templates/Fortunes.rocker.html

@@ -1,21 +0,0 @@
-@import java.util.*
-@import io.quarkus.benchmark.model.*
-@args(List fortunes)
-<!DOCTYPE html>
-<html>
-<head><title>Fortunes</title></head>
-<body>
-<table>
-    <tr>
-        <th>id</th>
-        <th>message</th>
-    </tr>
-    @for ((ForIterator i, Fortune fortune) : fortunes) {
-    <tr>
-        <td>@fortune.getId()</td>
-        <td>@fortune.getMessage()</td>
-    </tr>
-    }
-</table>
-</body>
-</html>

+ 27 - 23
frameworks/Java/quarkus/pom.xml

@@ -8,16 +8,19 @@
     <packaging>pom</packaging>
     <packaging>pom</packaging>
 
 
     <properties>
     <properties>
-        <quarkus.version>1.5.2.Final</quarkus.version>
+        <quarkus.version>1.11.0.Beta1</quarkus.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.source>11</maven.compiler.source>
         <maven.compiler.target>11</maven.compiler.target>
         <maven.compiler.target>11</maven.compiler.target>
     </properties>
     </properties>
 
 
     <modules>
     <modules>
-        <module>base</module>
-        <module>hibernate</module>
-        <module>pgclient</module>
+        <module>resteasy-hibernate</module>
+        <module>reactive-routes-hibernate-reactive</module>
+        <module>reactive-routes-pgclient</module>
+        <module>resteasy-reactive-pgclient</module>
+        <module>resteasy-reactive-hibernate</module>
+        <module>resteasy-reactive-hibernate-reactive</module>
     </modules>
     </modules>
 
 
     <dependencyManagement>
     <dependencyManagement>
@@ -34,28 +37,24 @@
                 <artifactId>base</artifactId>
                 <artifactId>base</artifactId>
                 <version>${project.version}</version>
                 <version>${project.version}</version>
             </dependency>
             </dependency>
+            <dependency>
+                <groupId>io.vertx</groupId>
+                <artifactId>vertx-pg-client</artifactId>
+                <version>3.9.0</version>
+            </dependency>
+            <dependency>
+                <groupId>io.vertx</groupId>
+                <artifactId>vertx-sql-client</artifactId>
+                <version>3.9.0</version>
+            </dependency>
+            <dependency>
+                <groupId>io.vertx</groupId>
+                <artifactId>vertx-web</artifactId>
+                <version>3.9.3</version>
+            </dependency>
         </dependencies>
         </dependencies>
     </dependencyManagement>
     </dependencyManagement>
 
 
-    <dependencies>
-        <dependency>
-            <groupId>io.quarkus</groupId>
-            <artifactId>quarkus-resteasy</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>io.quarkus</groupId>
-            <artifactId>quarkus-resteasy-jackson</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>io.quarkus</groupId>
-            <artifactId>quarkus-arc</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>io.quarkus</groupId>
-            <artifactId>quarkus-jdbc-postgresql</artifactId>
-        </dependency>
-    </dependencies>
-
     <build>
     <build>
         <plugins>
         <plugins>
             <plugin>
             <plugin>
@@ -90,6 +89,11 @@
                     </execution>
                     </execution>
                 </executions>
                 </executions>
             </plugin>
             </plugin>
+            <plugin>
+                <groupId>io.quarkus</groupId>
+                <artifactId>quarkus-bootstrap-maven-plugin</artifactId>
+                <version>${quarkus.version}</version>
+            </plugin>
         </plugins>
         </plugins>
     </build>
     </build>
     <profiles>
     <profiles>

+ 28 - 0
frameworks/Java/quarkus/quarkus-reactive-routes-hibernate-reactive.dockerfile

@@ -0,0 +1,28 @@
+FROM maven:3.6.3-jdk-11-slim as maven
+WORKDIR /quarkus
+ENV MODULE=reactive-routes-hibernate-reactive
+
+COPY pom.xml pom.xml
+COPY $MODULE/pom.xml $MODULE/pom.xml
+
+# Uncomment to test pre-release quarkus
+#RUN mkdir -p /root/.m2/repository/io
+#COPY m2-quarkus /root/.m2/repository/io/quarkus
+
+WORKDIR /quarkus/$MODULE
+RUN mvn dependency:go-offline -q
+WORKDIR /quarkus
+
+COPY $MODULE/src $MODULE/src
+
+WORKDIR /quarkus/$MODULE
+RUN mvn package -q
+WORKDIR /quarkus
+
+FROM openjdk:11.0.6-jdk-slim
+WORKDIR /quarkus
+ENV MODULE=reactive-routes-hibernate-reactive
+
+COPY --from=maven /quarkus/$MODULE/target/lib lib
+COPY --from=maven /quarkus/$MODULE/target/$MODULE-1.0-SNAPSHOT-runner.jar app.jar
+CMD ["java", "-server", "-XX:-UseBiasedLocking", "-XX:+UseStringDeduplication", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-Djava.lang.Integer.IntegerCache.high=10000", "-Dvertx.disableHttpHeadersValidation=true", "-Dvertx.disableMetrics=true", "-Dvertx.disableH2c=true", "-Dvertx.disableWebsockets=true", "-Dvertx.flashPolicyHandler=false", "-Dvertx.threadChecks=false", "-Dvertx.disableContextTimings=true", "-Dvertx.disableTCCL=true", "-Dhibernate.allow_update_outside_transaction=true", "-Djboss.threads.eqe.statistics=false", "-jar", "app.jar"]

+ 20 - 10
frameworks/Java/quarkus/quarkus-pgclient.dockerfile → frameworks/Java/quarkus/quarkus-reactive-routes-pgclient.dockerfile

@@ -1,18 +1,28 @@
 FROM maven:3.6.3-jdk-11-slim as maven
 FROM maven:3.6.3-jdk-11-slim as maven
 WORKDIR /quarkus
 WORKDIR /quarkus
+ENV MODULE=reactive-routes-pgclient
+
 COPY pom.xml pom.xml
 COPY pom.xml pom.xml
-COPY base/pom.xml base/pom.xml
-COPY hibernate/pom.xml hibernate/pom.xml
-COPY pgclient/pom.xml pgclient/pom.xml
-RUN mvn dependency:go-offline -q -pl base
-COPY base/src/main/resources base/src/main/resources
-COPY hibernate/src hibernate/src
-COPY pgclient/src pgclient/src
+COPY $MODULE/pom.xml $MODULE/pom.xml
+
+# Uncomment to test pre-release quarkus
+#RUN mkdir -p /root/.m2/repository/io
+#COPY m2-quarkus /root/.m2/repository/io/quarkus
+
+WORKDIR /quarkus/$MODULE
+RUN mvn dependency:go-offline -q
+WORKDIR /quarkus
 
 
-RUN mvn package -q -pl pgclient -am
+COPY $MODULE/src $MODULE/src
+
+WORKDIR /quarkus/$MODULE
+RUN mvn package -q
+WORKDIR /quarkus
 
 
 FROM openjdk:11.0.6-jdk-slim
 FROM openjdk:11.0.6-jdk-slim
 WORKDIR /quarkus
 WORKDIR /quarkus
-COPY --from=maven /quarkus/pgclient/target/lib lib
-COPY --from=maven /quarkus/pgclient/target/pgclient-1.0-SNAPSHOT-runner.jar app.jar
+ENV MODULE=reactive-routes-pgclient
+
+COPY --from=maven /quarkus/$MODULE/target/lib lib
+COPY --from=maven /quarkus/$MODULE/target/$MODULE-1.0-SNAPSHOT-runner.jar app.jar
 CMD ["java", "-server", "-XX:-UseBiasedLocking", "-XX:+UseStringDeduplication", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-Djava.lang.Integer.IntegerCache.high=10000", "-Dvertx.disableHttpHeadersValidation=true", "-Dvertx.disableMetrics=true", "-Dvertx.disableH2c=true", "-Dvertx.disableWebsockets=true", "-Dvertx.flashPolicyHandler=false", "-Dvertx.threadChecks=false", "-Dvertx.disableContextTimings=true", "-Dvertx.disableTCCL=true", "-Dhibernate.allow_update_outside_transaction=true", "-Djboss.threads.eqe.statistics=false", "-jar", "app.jar"]
 CMD ["java", "-server", "-XX:-UseBiasedLocking", "-XX:+UseStringDeduplication", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-Djava.lang.Integer.IntegerCache.high=10000", "-Dvertx.disableHttpHeadersValidation=true", "-Dvertx.disableMetrics=true", "-Dvertx.disableH2c=true", "-Dvertx.disableWebsockets=true", "-Dvertx.flashPolicyHandler=false", "-Dvertx.threadChecks=false", "-Dvertx.disableContextTimings=true", "-Dvertx.disableTCCL=true", "-Dhibernate.allow_update_outside_transaction=true", "-Djboss.threads.eqe.statistics=false", "-jar", "app.jar"]

+ 28 - 0
frameworks/Java/quarkus/quarkus-resteasy-reactive-hibernate-reactive.dockerfile

@@ -0,0 +1,28 @@
+FROM maven:3.6.3-jdk-11-slim as maven
+WORKDIR /quarkus
+ENV MODULE=resteasy-reactive-hibernate-reactive
+
+COPY pom.xml pom.xml
+COPY $MODULE/pom.xml $MODULE/pom.xml
+
+# Uncomment to test pre-release quarkus
+#RUN mkdir -p /root/.m2/repository/io
+#COPY m2-quarkus /root/.m2/repository/io/quarkus
+
+WORKDIR /quarkus/$MODULE
+RUN mvn dependency:go-offline -q
+WORKDIR /quarkus
+
+COPY $MODULE/src $MODULE/src
+
+WORKDIR /quarkus/$MODULE
+RUN mvn package -q
+WORKDIR /quarkus
+
+FROM openjdk:11.0.6-jdk-slim
+WORKDIR /quarkus
+ENV MODULE=resteasy-reactive-hibernate-reactive
+
+COPY --from=maven /quarkus/$MODULE/target/lib lib
+COPY --from=maven /quarkus/$MODULE/target/$MODULE-1.0-SNAPSHOT-runner.jar app.jar
+CMD ["java", "-server", "-XX:-UseBiasedLocking", "-XX:+UseStringDeduplication", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-Djava.lang.Integer.IntegerCache.high=10000", "-Dvertx.disableHttpHeadersValidation=true", "-Dvertx.disableMetrics=true", "-Dvertx.disableH2c=true", "-Dvertx.disableWebsockets=true", "-Dvertx.flashPolicyHandler=false", "-Dvertx.threadChecks=false", "-Dvertx.disableContextTimings=true", "-Dvertx.disableTCCL=true", "-Dhibernate.allow_update_outside_transaction=true", "-Djboss.threads.eqe.statistics=false", "-jar", "app.jar"]

+ 28 - 0
frameworks/Java/quarkus/quarkus-resteasy-reactive-hibernate.dockerfile

@@ -0,0 +1,28 @@
+FROM maven:3.6.3-jdk-11-slim as maven
+WORKDIR /quarkus
+ENV MODULE=resteasy-reactive-hibernate
+
+COPY pom.xml pom.xml
+COPY $MODULE/pom.xml $MODULE/pom.xml
+
+# Uncomment to test pre-release quarkus
+#RUN mkdir -p /root/.m2/repository/io
+#COPY m2-quarkus /root/.m2/repository/io/quarkus
+
+WORKDIR /quarkus/$MODULE
+RUN mvn dependency:go-offline -q
+WORKDIR /quarkus
+
+COPY $MODULE/src $MODULE/src
+
+WORKDIR /quarkus/$MODULE
+RUN mvn package -q
+WORKDIR /quarkus
+
+FROM openjdk:11.0.6-jdk-slim
+WORKDIR /quarkus
+ENV MODULE=resteasy-reactive-hibernate
+
+COPY --from=maven /quarkus/$MODULE/target/lib lib
+COPY --from=maven /quarkus/$MODULE/target/$MODULE-1.0-SNAPSHOT-runner.jar app.jar
+CMD ["java", "-server", "-XX:-UseBiasedLocking", "-XX:+UseStringDeduplication", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-Djava.lang.Integer.IntegerCache.high=10000", "-Dvertx.disableHttpHeadersValidation=true", "-Dvertx.disableMetrics=true", "-Dvertx.disableH2c=true", "-Dvertx.disableWebsockets=true", "-Dvertx.flashPolicyHandler=false", "-Dvertx.threadChecks=false", "-Dvertx.disableContextTimings=true", "-Dvertx.disableTCCL=true", "-Dhibernate.allow_update_outside_transaction=true", "-Djboss.threads.eqe.statistics=false", "-jar", "app.jar"]

+ 28 - 0
frameworks/Java/quarkus/quarkus-resteasy-reactive-pgclient.dockerfile

@@ -0,0 +1,28 @@
+FROM maven:3.6.3-jdk-11-slim as maven
+WORKDIR /quarkus
+ENV MODULE=resteasy-reactive-pgclient
+
+COPY pom.xml pom.xml
+COPY $MODULE/pom.xml $MODULE/pom.xml
+
+# Uncomment to test pre-release quarkus
+#RUN mkdir -p /root/.m2/repository/io
+#COPY m2-quarkus /root/.m2/repository/io/quarkus
+
+WORKDIR /quarkus/$MODULE
+RUN mvn dependency:go-offline -q
+WORKDIR /quarkus
+
+COPY $MODULE/src $MODULE/src
+
+WORKDIR /quarkus/$MODULE
+RUN mvn package -q
+WORKDIR /quarkus
+
+FROM openjdk:11.0.6-jdk-slim
+WORKDIR /quarkus
+ENV MODULE=resteasy-reactive-pgclient
+
+COPY --from=maven /quarkus/$MODULE/target/lib lib
+COPY --from=maven /quarkus/$MODULE/target/$MODULE-1.0-SNAPSHOT-runner.jar app.jar
+CMD ["java", "-server", "-XX:-UseBiasedLocking", "-XX:+UseStringDeduplication", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-Djava.lang.Integer.IntegerCache.high=10000", "-Dvertx.disableHttpHeadersValidation=true", "-Dvertx.disableMetrics=true", "-Dvertx.disableH2c=true", "-Dvertx.disableWebsockets=true", "-Dvertx.flashPolicyHandler=false", "-Dvertx.threadChecks=false", "-Dvertx.disableContextTimings=true", "-Dvertx.disableTCCL=true", "-Dhibernate.allow_update_outside_transaction=true", "-Djboss.threads.eqe.statistics=false", "-jar", "app.jar"]

+ 20 - 10
frameworks/Java/quarkus/quarkus.dockerfile

@@ -1,18 +1,28 @@
 FROM maven:3.6.3-jdk-11-slim as maven
 FROM maven:3.6.3-jdk-11-slim as maven
 WORKDIR /quarkus
 WORKDIR /quarkus
+ENV MODULE=resteasy-hibernate
+
 COPY pom.xml pom.xml
 COPY pom.xml pom.xml
-COPY base/pom.xml base/pom.xml
-COPY hibernate/pom.xml hibernate/pom.xml
-COPY pgclient/pom.xml pgclient/pom.xml
-RUN mvn dependency:go-offline -q -pl base
-COPY base/src base/src
-COPY hibernate/src hibernate/src
-COPY pgclient/src pgclient/src
+COPY $MODULE/pom.xml $MODULE/pom.xml
+
+# Uncomment to test pre-release quarkus
+#RUN mkdir -p /root/.m2/repository/io
+#COPY m2-quarkus /root/.m2/repository/io/quarkus
+
+WORKDIR /quarkus/$MODULE
+RUN mvn dependency:go-offline -q
+WORKDIR /quarkus
 
 
-RUN mvn package -q -pl hibernate -am
+COPY $MODULE/src $MODULE/src
+
+WORKDIR /quarkus/$MODULE
+RUN mvn package -q
+WORKDIR /quarkus
 
 
 FROM openjdk:11.0.6-jdk-slim
 FROM openjdk:11.0.6-jdk-slim
 WORKDIR /quarkus
 WORKDIR /quarkus
-COPY --from=maven /quarkus/hibernate/target/lib lib
-COPY --from=maven /quarkus/hibernate/target/hibernate-1.0-SNAPSHOT-runner.jar app.jar
+ENV MODULE=resteasy-hibernate
+
+COPY --from=maven /quarkus/$MODULE/target/lib lib
+COPY --from=maven /quarkus/$MODULE/target/$MODULE-1.0-SNAPSHOT-runner.jar app.jar
 CMD ["java", "-server", "-XX:-UseBiasedLocking", "-XX:+UseStringDeduplication", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-Djava.lang.Integer.IntegerCache.high=10000", "-Dvertx.disableHttpHeadersValidation=true", "-Dvertx.disableMetrics=true", "-Dvertx.disableH2c=true", "-Dvertx.disableWebsockets=true", "-Dvertx.flashPolicyHandler=false", "-Dvertx.threadChecks=false", "-Dvertx.disableContextTimings=true", "-Dvertx.disableTCCL=true", "-Dhibernate.allow_update_outside_transaction=true", "-Djboss.threads.eqe.statistics=false", "-jar", "app.jar"]
 CMD ["java", "-server", "-XX:-UseBiasedLocking", "-XX:+UseStringDeduplication", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-Djava.lang.Integer.IntegerCache.high=10000", "-Dvertx.disableHttpHeadersValidation=true", "-Dvertx.disableMetrics=true", "-Dvertx.disableH2c=true", "-Dvertx.disableWebsockets=true", "-Dvertx.flashPolicyHandler=false", "-Dvertx.threadChecks=false", "-Dvertx.disableContextTimings=true", "-Dvertx.disableTCCL=true", "-Dhibernate.allow_update_outside_transaction=true", "-Djboss.threads.eqe.statistics=false", "-jar", "app.jar"]

+ 46 - 0
frameworks/Java/quarkus/reactive-routes-hibernate-reactive/pom.xml

@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project>
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>io.quarkus</groupId>
+        <artifactId>benchmark</artifactId>
+        <version>1.0-SNAPSHOT</version>
+        <relativePath>../</relativePath>
+    </parent>
+
+    <groupId>io.quarkus.benchmark</groupId>
+    <artifactId>reactive-routes-hibernate-reactive</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-reactive-pg-client</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-scheduler</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-hibernate-reactive</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-vertx-web</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.github.spullara.mustache.java</groupId>
+            <artifactId>compiler</artifactId>
+            <version>0.9.6</version>
+        </dependency>
+        <dependency>
+            <groupId>io.vertx</groupId>
+            <artifactId>vertx-pg-client</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.vertx</groupId>
+            <artifactId>vertx-sql-client</artifactId>
+        </dependency>
+    </dependencies>
+</project>

+ 1 - 1
frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/resource/pgclient/ServerHeaderFilter.java → frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/filter/ServerHeaderFilter.java

@@ -1,4 +1,4 @@
-package io.quarkus.benchmark.resource.pgclient;
+package io.quarkus.benchmark.filter;
 
 
 import java.time.ZonedDateTime;
 import java.time.ZonedDateTime;
 import java.time.format.DateTimeFormatter;
 import java.time.format.DateTimeFormatter;

+ 1 - 1
frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/model/hibernate/Fortune.java → frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/model/Fortune.java

@@ -1,4 +1,4 @@
-package io.quarkus.benchmark.model.hibernate;
+package io.quarkus.benchmark.model;
 
 
 import org.hibernate.annotations.Immutable;
 import org.hibernate.annotations.Immutable;
 
 

+ 1 - 1
frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/model/hibernate/World.java → frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/model/World.java

@@ -1,4 +1,4 @@
-package io.quarkus.benchmark.model.hibernate;
+package io.quarkus.benchmark.model;
 
 
 import javax.persistence.Entity;
 import javax.persistence.Entity;
 import javax.persistence.Id;
 import javax.persistence.Id;

+ 19 - 0
frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/repository/BaseRepository.java

@@ -0,0 +1,19 @@
+package io.quarkus.benchmark.repository;
+
+import java.util.function.Function;
+
+import javax.inject.Inject;
+
+import org.hibernate.reactive.mutiny.Mutiny;
+
+import io.smallrye.mutiny.Uni;
+
+public class BaseRepository {
+    @Inject
+    protected Mutiny.SessionFactory sf;
+
+    public <T> Uni<T> inSession(Function<Mutiny.Session, Uni<T>> work){
+        return sf.withSession(session -> work.apply(session));
+    }
+
+}

+ 25 - 0
frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/repository/FortuneRepository.java

@@ -0,0 +1,25 @@
+package io.quarkus.benchmark.repository;
+
+import java.util.List;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Root;
+
+import io.quarkus.benchmark.model.Fortune;
+import io.smallrye.mutiny.Uni;
+
+@ApplicationScoped
+public class FortuneRepository extends BaseRepository {
+
+    public Uni<List<Fortune>> findAll() {
+        return inSession(s -> {
+            CriteriaBuilder criteriaBuilder = sf.getCriteriaBuilder();
+            CriteriaQuery<Fortune> fortuneQuery = criteriaBuilder.createQuery(Fortune.class);
+            Root<Fortune> from = fortuneQuery.from(Fortune.class);
+            fortuneQuery.select(from);
+            return s.createQuery(fortuneQuery).getResultList();
+        });
+    }
+}

+ 65 - 0
frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/repository/WorldRepository.java

@@ -0,0 +1,65 @@
+package io.quarkus.benchmark.repository;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ThreadLocalRandom;
+
+import javax.inject.Singleton;
+
+import org.hibernate.reactive.mutiny.Mutiny;
+import org.hibernate.reactive.mutiny.Mutiny.Session;
+
+import io.quarkus.benchmark.model.World;
+import io.smallrye.mutiny.Uni;
+
+
+@Singleton
+public class WorldRepository extends BaseRepository {
+
+    /**
+     * This method is not required (nor specified) by the benchmark rules,
+     * but is quite handy to seed a local database and be able to experiment
+     * with the app locally.
+     */
+    public Uni<Void> createData() {
+        return inSession(s -> {
+            final ThreadLocalRandom random = ThreadLocalRandom.current();
+            int MAX = 10000;
+            Uni<Void>[] unis = new Uni[MAX];
+            for (int i=0; i<MAX; i++) {
+                final World world = new World();
+                world.setId(i + 1);
+                world.setRandomNumber(1 + random.nextInt(10000));
+                unis[i] = s.persist(world).map(v -> null);
+            }
+            return Uni.combine().all().unis(unis).combinedWith(l -> null)
+                    .flatMap(v -> s.flush())
+                    .map(v -> null);
+        });
+    }
+
+    public Uni<World> find(int id) {
+        return inSession(session -> singleFind(session, id));
+    }
+
+    public Uni<Collection<World>> update(Mutiny.Session s, Collection<World> worlds) {
+        return s.flush()
+                .map(v -> worlds);
+            }
+
+    public Uni<Collection<World>> find(Session s, Set<Integer> ids) {
+        //The rules require individual load: we can't use the Hibernate feature which allows load by multiple IDs as one single operation
+        ArrayList<Uni<World>> l = new ArrayList<>(ids.size());
+        for (Integer id : ids) {
+            l.add(singleFind(s, id));
+        }
+        return Uni.combine().all().unis(l).combinedWith(list -> (List<World>)list);
+    }
+
+    private static Uni<World> singleFind(final Mutiny.Session ss, final Integer id) {
+        return ss.find(World.class, id);
+    }
+
+}

+ 34 - 0
frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/resource/BaseResource.java

@@ -0,0 +1,34 @@
+package io.quarkus.benchmark.resource;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import javax.inject.Inject;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import io.vertx.ext.web.RoutingContext;
+
+public abstract class BaseResource {
+    
+    @Inject
+    ObjectMapper mapper;
+
+    void sendJson(RoutingContext rc, Object value) {
+        try {
+            rc.response().putHeader("Content-Type", "application/json");
+            rc.response().end(mapper.writeValueAsString(value));
+        } catch (JsonProcessingException e) {
+            throw new RuntimeException(e);
+        }   
+    }
+
+    Void handleFail(RoutingContext rc, Throwable t) {
+        var sw = new StringWriter();
+        t.printStackTrace(new PrintWriter(sw));
+        rc.response().setStatusCode(500).end(sw.toString());
+        return null;
+    }
+
+}

+ 130 - 0
frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/resource/DbResource.java

@@ -0,0 +1,130 @@
+package io.quarkus.benchmark.resource;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.ThreadLocalRandom;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+
+import org.hibernate.FlushMode;
+import org.hibernate.reactive.mutiny.Mutiny;
+
+import io.quarkus.benchmark.model.World;
+import io.quarkus.benchmark.repository.WorldRepository;
+import io.quarkus.vertx.web.Route;
+import io.smallrye.mutiny.Uni;
+import io.vertx.ext.web.RoutingContext;
+
+
+@ApplicationScoped
+public class DbResource extends BaseResource {
+
+    @Inject
+    WorldRepository worldRepository;
+
+    @Route(path = "db")
+    public void db(RoutingContext rc) {
+        randomWorld().subscribe().with(world -> sendJson(rc, world),
+                                       t -> handleFail(rc, t));
+    }
+
+    @Route(path = "queries")
+    public void queries(RoutingContext rc) {
+        var queries = rc.request().getParam("queries");
+        worldRepository.inSession(session -> randomWorldForRead(session, parseQueryCount(queries)))
+        .subscribe().with(list -> sendJson(rc, list),
+                          t -> handleFail(rc, t));
+    }
+
+    //Rules: https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Framework-Tests-Overview#database-updates
+    //N.B. the benchmark seems to be designed to get in deadlocks when using a "safe pattern" of updating
+    // the entity within the same transaction as the one which read it.
+    // We therefore need to do a "read then write" while relinquishing the transaction between the two operations, as
+    // all other tested frameworks seem to do.
+    @Route(path = "updates")
+    public void updates(RoutingContext rc) {
+        var queries = rc.request().getParam("queries");
+        worldRepository.inSession(session -> {
+            // FIXME: not supported
+            //          session.setJdbcBatchSize(worlds.size());
+            session.setFlushMode(FlushMode.MANUAL);
+
+            var worlds = randomWorldForRead(session, parseQueryCount(queries));
+            return worlds.flatMap(worldsCollection -> {
+                worldsCollection.forEach( w -> {
+                    //Read the one field, as required by the following rule:
+                    // # vi. At least the randomNumber field must be read from the database result set.
+                    final int previousRead = w.getRandomNumber();
+                    //Update it, but make sure to exclude the current number as Hibernate optimisations would have us "fail"
+                    //the verification:
+                    w.setRandomNumber(randomWorldNumber(previousRead));
+                } );
+                
+                return worldRepository.update(session, worldsCollection);
+            });
+        }).subscribe().with(list -> sendJson(rc, list),
+                            t -> handleFail(rc, t));
+    }
+
+    private Uni<Collection<World>> randomWorldForRead(Mutiny.Session session, int count) {
+        Set<Integer> ids = new HashSet<>(count);
+        int counter = 0;
+        while (counter < count) {
+            counter += ids.add(Integer.valueOf(randomWorldNumber())) ? 1 : 0;
+        }
+        return worldRepository.find(session, ids);
+    }
+
+    @Route(path = "createdata")
+    public void createData(RoutingContext rc) {
+        worldRepository.createData().subscribe().with(v -> rc.response().end("Data created"),
+                                                      t -> handleFail(rc, t));
+    }
+
+    private Uni<World> randomWorld() {
+        int i = randomWorldNumber();
+        return worldRepository.find(i);
+    }
+
+    private int randomWorldNumber() {
+        return 1 + ThreadLocalRandom.current().nextInt(10000);
+    }
+
+    /**
+     * Also according to benchmark requirements, except that in this special case
+     * of the update test we need to ensure we'll actually generate an update operation:
+     * for this we need to generate a random number between 1 to 10000, but different
+     * from the current field value.
+     * @param previousRead
+     * @return
+     */
+    private int randomWorldNumber(final int previousRead) {
+        //conceptually split the random space in those before previousRead,
+        //and those after: this approach makes sure to not affect the random characteristics.
+        final int trueRandom = ThreadLocalRandom.current().nextInt(9999) + 2;
+        if (trueRandom<=previousRead) {
+            //all figures equal or before the current field read need to be shifted back by one
+            //so to avoid hitting the same number while not affecting the distribution.
+            return trueRandom - 1;
+        }
+        else {
+            //Those after are generated by taking the generated value 2...10000 as is.
+            return trueRandom;
+        }
+    }
+
+    private int parseQueryCount(String textValue) {
+        if (textValue == null) {
+            return 1;
+        }
+        int parsedValue;
+        try {
+            parsedValue = Integer.parseInt(textValue);
+        } catch (NumberFormatException e) {
+            return 1;
+        }
+        return Math.min(500, Math.max(1, parsedValue));
+    }
+}

+ 47 - 0
frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/resource/FortuneResource.java

@@ -0,0 +1,47 @@
+package io.quarkus.benchmark.resource;
+
+import java.io.StringWriter;
+import java.util.Collections;
+import java.util.Comparator;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+
+import com.github.mustachejava.DefaultMustacheFactory;
+import com.github.mustachejava.Mustache;
+import com.github.mustachejava.MustacheFactory;
+
+import io.quarkus.benchmark.model.Fortune;
+import io.quarkus.benchmark.repository.FortuneRepository;
+import io.quarkus.vertx.web.Route;
+import io.vertx.ext.web.RoutingContext;
+
+@ApplicationScoped
+public class FortuneResource extends BaseResource {
+
+    @Inject
+    FortuneRepository repository;
+
+    private final Mustache template;
+    private Comparator<Fortune> fortuneComparator;
+
+    public FortuneResource() {
+        MustacheFactory mf = new DefaultMustacheFactory();
+        template = mf.compile("fortunes.mustache");
+        fortuneComparator = Comparator.comparing(fortune -> fortune.getMessage());
+    }
+
+    @Route(path = "fortunes")
+    public void fortunes(RoutingContext rc) {
+        repository.findAll()
+        .subscribe().with( fortunes -> {
+            fortunes.add(new Fortune(0, "Additional fortune added at request time."));
+            fortunes.sort(fortuneComparator);
+            StringWriter writer = new StringWriter();
+            template.execute(writer, Collections.singletonMap("fortunes", fortunes));
+            rc.response().putHeader("Content-Type", "text/html;charset=UTF-8");
+            rc.response().end(writer.toString());
+        },
+                           t -> handleFail(rc, t));
+    }
+}

+ 21 - 0
frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/resource/JsonResource.java

@@ -0,0 +1,21 @@
+package io.quarkus.benchmark.resource;
+
+import java.util.Collections;
+
+import javax.enterprise.context.ApplicationScoped;
+
+import io.quarkus.vertx.web.Route;
+import io.vertx.ext.web.RoutingContext;
+
+@ApplicationScoped
+public class JsonResource extends BaseResource {
+
+    private static final String MESSAGE = "message";
+    private static final String HELLO = "Hello, World!";
+
+    @Route(path = "json")
+    public void json(RoutingContext rc) {
+        sendJson(rc, Collections.singletonMap( MESSAGE, HELLO ));
+    }
+}
+

+ 2 - 3
frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/resource/pgclient/PlaintextResource.java → frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/resource/PlaintextResource.java

@@ -1,14 +1,13 @@
-package io.quarkus.benchmark.resource.pgclient;
+package io.quarkus.benchmark.resource;
 
 
 import javax.enterprise.context.ApplicationScoped;
 import javax.enterprise.context.ApplicationScoped;
 
 
 import io.quarkus.vertx.web.Route;
 import io.quarkus.vertx.web.Route;
-import io.vertx.core.buffer.Buffer;
 import io.vertx.ext.web.RoutingContext;
 import io.vertx.ext.web.RoutingContext;
 
 
 @ApplicationScoped
 @ApplicationScoped
 public class PlaintextResource {
 public class PlaintextResource {
-    private static final Buffer HELLO = Buffer.buffer("Hello, World!");
+    private static final String HELLO = "Hello, World!";
 
 
     @Route(path = "plaintext")
     @Route(path = "plaintext")
     public void plaintext(RoutingContext rc) {
     public void plaintext(RoutingContext rc) {

+ 20 - 0
frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/resources/application.properties

@@ -0,0 +1,20 @@
+quarkus.datasource.db-kind=postgresql
+quarkus.datasource.username=benchmarkdbuser
+quarkus.datasource.password=benchmarkdbpass
+#quarkus.datasource.max-size=64
+
+# Reactive config
+quarkus.datasource.reactive=true
+quarkus.datasource.reactive.url=postgresql://tfb-database:5432/hello_world
+%dev.quarkus.datasource.reactive.url=postgresql://localhost:5432/hello_world
+
+quarkus.datasource.reactive.thread-local=true
+quarkus.datasource.reactive.cache-prepared-statements=true
+quarkus.datasource.reactive.max-size=4
+
+#quarkus.vertx.storage=false
+
+quarkus.log.console.enable=true
+quarkus.log.console.level=INFO
+quarkus.log.file.enable=false
+quarkus.log.level=INFO

+ 0 - 0
frameworks/Java/quarkus/base/src/main/resources/fortunes.mustache → frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/resources/fortunes.mustache


+ 0 - 0
frameworks/Java/quarkus/pgclient/start-app.sh → frameworks/Java/quarkus/reactive-routes-hibernate-reactive/start-app.sh


+ 8 - 26
frameworks/Java/quarkus/pgclient/pom.xml → frameworks/Java/quarkus/reactive-routes-pgclient/pom.xml

@@ -10,12 +10,12 @@
     </parent>
     </parent>
 
 
     <groupId>io.quarkus.benchmark</groupId>
     <groupId>io.quarkus.benchmark</groupId>
-    <artifactId>pgclient</artifactId>
+    <artifactId>reactive-routes-pgclient</artifactId>
 
 
     <dependencies>
     <dependencies>
         <dependency>
         <dependency>
-            <groupId>io.quarkus.benchmark</groupId>
-            <artifactId>base</artifactId>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-scheduler</artifactId>
         </dependency>
         </dependency>
         <dependency>
         <dependency>
             <groupId>io.quarkus</groupId>
             <groupId>io.quarkus</groupId>
@@ -34,28 +34,10 @@
             <artifactId>netty-transport-native-epoll</artifactId>
             <artifactId>netty-transport-native-epoll</artifactId>
             <classifier>linux-x86_64</classifier>
             <classifier>linux-x86_64</classifier>
         </dependency>
         </dependency>
+        <dependency>
+            <groupId>com.github.spullara.mustache.java</groupId>
+            <artifactId>compiler</artifactId>
+            <version>0.9.6</version>
+        </dependency>
     </dependencies>
     </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>com.fizzed</groupId>
-                <artifactId>rocker-maven-plugin</artifactId>
-                <version>1.3.0</version>
-                <executions>
-                    <execution>
-                        <id>generate-rocker-templates</id>
-                        <phase>generate-sources</phase>
-                        <goals>
-                            <goal>generate</goal>
-                        </goals>
-                        <configuration>
-                            <templateDirectory>${project.basedir}/src/main/resources</templateDirectory>
-                            <optimize>true</optimize>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-
-    </build>
 </project>
 </project>

+ 33 - 0
frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/filter/ServerHeaderFilter.java

@@ -0,0 +1,33 @@
+package io.quarkus.benchmark.filter;
+
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+
+import javax.inject.Singleton;
+
+import io.quarkus.scheduler.Scheduled;
+import io.quarkus.vertx.web.RouteFilter;
+import io.vertx.core.http.HttpHeaders;
+import io.vertx.ext.web.RoutingContext;
+
+@Singleton
+public class ServerHeaderFilter {
+
+    private static final CharSequence SERVER_HEADER_NAME = HttpHeaders.createOptimized("Server");
+    private static final CharSequence SERVER_HEADER_VALUE = HttpHeaders.createOptimized("Quarkus");
+    private static final CharSequence DATE_HEADER_NAME = HttpHeaders.createOptimized("Date");
+
+    private CharSequence date;
+
+    @Scheduled(every="1s")
+    void increment() {
+        date = HttpHeaders.createOptimized(DateTimeFormatter.RFC_1123_DATE_TIME.format(ZonedDateTime.now()));
+    }
+
+    @RouteFilter(100) 
+    void myFilter(RoutingContext rc) {
+       rc.response().putHeader( SERVER_HEADER_NAME, SERVER_HEADER_VALUE);
+       rc.response().putHeader( DATE_HEADER_NAME, date);
+       rc.next(); 
+    }
+}

+ 0 - 0
frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/model/Fortune.java → frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/model/Fortune.java


+ 0 - 0
frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/model/World.java → frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/model/World.java


+ 1 - 1
frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/repository/pgclient/FortuneRepository.java → frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/repository/FortuneRepository.java

@@ -1,4 +1,4 @@
-package io.quarkus.benchmark.repository.pgclient;
+package io.quarkus.benchmark.repository;
 
 
 import java.util.ArrayList;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.List;

+ 1 - 1
frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/repository/pgclient/PgClientFactory.java → frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/repository/PgClientFactory.java

@@ -1,4 +1,4 @@
-package io.quarkus.benchmark.repository.pgclient;
+package io.quarkus.benchmark.repository;
 
 
 import java.util.regex.Matcher;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.regex.Pattern;

+ 1 - 1
frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/repository/pgclient/PgClients.java → frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/repository/PgClients.java

@@ -1,4 +1,4 @@
-package io.quarkus.benchmark.repository.pgclient;
+package io.quarkus.benchmark.repository;
 
 
 import io.vertx.mutiny.pgclient.PgPool;
 import io.vertx.mutiny.pgclient.PgPool;
 import io.vertx.mutiny.sqlclient.SqlClient;
 import io.vertx.mutiny.sqlclient.SqlClient;

+ 1 - 1
frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/repository/pgclient/WorldRepository.java → frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/repository/WorldRepository.java

@@ -1,4 +1,4 @@
-package io.quarkus.benchmark.repository.pgclient;
+package io.quarkus.benchmark.repository;
 
 
 import java.util.ArrayList;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Arrays;

+ 1 - 1
frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/resource/pgclient/BaseResource.java → frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/resource/BaseResource.java

@@ -1,4 +1,4 @@
-package io.quarkus.benchmark.resource.pgclient;
+package io.quarkus.benchmark.resource;
 
 
 import io.vertx.core.http.HttpHeaders;
 import io.vertx.core.http.HttpHeaders;
 import io.vertx.core.json.Json;
 import io.vertx.core.json.Json;

+ 4 - 4
frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/resource/pgclient/DbResource.java → frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/resource/DbResource.java

@@ -1,4 +1,4 @@
-package io.quarkus.benchmark.resource.pgclient;
+package io.quarkus.benchmark.resource;
 
 
 import java.util.Arrays;
 import java.util.Arrays;
 import java.util.concurrent.ThreadLocalRandom;
 import java.util.concurrent.ThreadLocalRandom;
@@ -7,7 +7,7 @@ import javax.enterprise.context.ApplicationScoped;
 import javax.inject.Inject;
 import javax.inject.Inject;
 
 
 import io.quarkus.benchmark.model.World;
 import io.quarkus.benchmark.model.World;
-import io.quarkus.benchmark.repository.pgclient.WorldRepository;
+import io.quarkus.benchmark.repository.WorldRepository;
 import io.quarkus.vertx.web.Route;
 import io.quarkus.vertx.web.Route;
 import io.smallrye.mutiny.Uni;
 import io.smallrye.mutiny.Uni;
 import io.smallrye.mutiny.groups.UniAndGroupIterable;
 import io.smallrye.mutiny.groups.UniAndGroupIterable;
@@ -35,7 +35,7 @@ public class DbResource extends BaseResource {
             return randomWorld().map(w -> ret[i] = w);
             return randomWorld().map(w -> ret[i] = w);
         });
         });
 
 
-        ((UniAndGroupIterable<Void>)Uni.combine().all().unis(worlds))
+        Uni.combine().all().unis(worlds)
         .combinedWith(v -> Arrays.asList(ret))
         .combinedWith(v -> Arrays.asList(ret))
         .subscribe().with(list -> sendJson(rc, list),
         .subscribe().with(list -> sendJson(rc, list),
                           t -> handleFail(rc, t));
                           t -> handleFail(rc, t));
@@ -54,7 +54,7 @@ public class DbResource extends BaseResource {
             });
             });
         });
         });
 
 
-        ((UniAndGroupIterable<Void>)Uni.combine().all().unis(worlds))
+        Uni.combine().all().unis(worlds)
         .combinedWith(v -> null)
         .combinedWith(v -> null)
         .flatMap(v -> worldRepository.update(ret))
         .flatMap(v -> worldRepository.update(ret))
         .map(v -> Arrays.asList(ret))
         .map(v -> Arrays.asList(ret))

+ 49 - 0
frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/resource/FortuneResource.java

@@ -0,0 +1,49 @@
+package io.quarkus.benchmark.resource;
+
+import java.io.StringWriter;
+import java.util.Collections;
+import java.util.Comparator;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+
+import com.github.mustachejava.DefaultMustacheFactory;
+import com.github.mustachejava.Mustache;
+import com.github.mustachejava.MustacheFactory;
+
+import io.quarkus.benchmark.model.Fortune;
+import io.quarkus.benchmark.repository.FortuneRepository;
+import io.quarkus.vertx.web.Route;
+import io.vertx.core.http.HttpHeaders;
+import io.vertx.ext.web.RoutingContext;
+
+@ApplicationScoped
+public class FortuneResource extends BaseResource {
+
+    @Inject
+    FortuneRepository repository;
+    private Mustache template;
+    private Comparator<Fortune> fortuneComparator;
+
+
+    public FortuneResource() {
+        MustacheFactory mf = new DefaultMustacheFactory();
+        template = mf.compile("fortunes.mustache");
+        fortuneComparator = Comparator.comparing(fortune -> fortune.getMessage());
+    }
+
+    @Route(path = "fortunes")
+    public void fortunes(RoutingContext rc) {
+        repository.findAll()
+                .subscribe().with(fortunes -> {
+                    fortunes.add(new Fortune(0, "Additional fortune added at request time."));
+                    fortunes.sort(fortuneComparator);
+                    StringWriter writer = new StringWriter();
+                    template.execute(writer, Collections.singletonMap("fortunes", fortunes));
+                    rc.response()
+                    .putHeader(HttpHeaders.CONTENT_TYPE, "text/html; charset=UTF-8")
+                    .end(writer.toString());
+                },
+                t -> handleFail(rc, t));
+    }
+}

+ 1 - 1
frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/resource/pgclient/JsonResource.java → frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/resource/JsonResource.java

@@ -1,4 +1,4 @@
-package io.quarkus.benchmark.resource.pgclient;
+package io.quarkus.benchmark.resource;
 
 
 import javax.enterprise.context.ApplicationScoped;
 import javax.enterprise.context.ApplicationScoped;
 
 

+ 1 - 1
frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/resource/pgclient/Message.java → frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/resource/Message.java

@@ -1,4 +1,4 @@
-package io.quarkus.benchmark.resource.pgclient;
+package io.quarkus.benchmark.resource;
 
 
 public class Message {
 public class Message {
   private final String message;
   private final String message;

+ 23 - 0
frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/resource/PlaintextResource.java

@@ -0,0 +1,23 @@
+package io.quarkus.benchmark.resource;
+
+import javax.enterprise.context.ApplicationScoped;
+
+import io.quarkus.vertx.web.Route;
+import io.vertx.core.buffer.Buffer;
+import io.vertx.core.http.HttpHeaders;
+import io.vertx.ext.web.RoutingContext;
+
+@ApplicationScoped
+public class PlaintextResource {
+    private static final String HELLO_WORLD = "Hello, world!";
+    private static final Buffer HELLO_WORLD_BUFFER = Buffer.factory.directBuffer(HELLO_WORLD, "UTF-8");
+
+    private static final CharSequence CONTENT_TYPE_HEADER_NAME = HttpHeaders.createOptimized("Content-Type");
+    private static final CharSequence CONTENT_TYPE_HEADER_VALUE = HttpHeaders.createOptimized("text/plain");
+
+    @Route(path = "plaintext")
+    public void plaintext(RoutingContext rc) {
+        rc.response().putHeader(CONTENT_TYPE_HEADER_NAME, CONTENT_TYPE_HEADER_VALUE);
+        rc.response().end(HELLO_WORLD_BUFFER);
+    }
+}

+ 1 - 1
frameworks/Java/quarkus/pgclient/src/main/resources/application.properties → frameworks/Java/quarkus/reactive-routes-pgclient/src/main/resources/application.properties

@@ -1,7 +1,7 @@
 quarkus.datasource.url=vertx-reactive:postgresql://tfb-database:5432/hello_world
 quarkus.datasource.url=vertx-reactive:postgresql://tfb-database:5432/hello_world
 quarkus.datasource.username=benchmarkdbuser
 quarkus.datasource.username=benchmarkdbuser
 quarkus.datasource.password=benchmarkdbpass
 quarkus.datasource.password=benchmarkdbpass
-quarkus.datasource.max-size=64
+quarkus.datasource.reactive.max-size=64
 quarkus.log.console.enable=true
 quarkus.log.console.enable=true
 quarkus.log.console.level=INFO
 quarkus.log.console.level=INFO
 quarkus.log.file.enable=false
 quarkus.log.file.enable=false

+ 20 - 0
frameworks/Java/quarkus/reactive-routes-pgclient/src/main/resources/fortunes.mustache

@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Fortunes</title>
+</head>
+<body>
+<table>
+    <tr>
+        <th>id</th>
+        <th>message</th>
+    </tr>
+    {{#fortunes}}
+        <tr>
+            <td>{{id}}</td>
+            <td>{{message}}</td>
+        </tr>
+    {{/fortunes}}
+</table>
+</body>
+</html>

+ 2 - 0
frameworks/Java/quarkus/reactive-routes-pgclient/start-app.sh

@@ -0,0 +1,2 @@
+java -XX:+FlightRecorder -XX:+UseParallelGC -Dquarkus.datasource.url=vertx-reactive:postgresql://localhost:5432/hello_world -Dquarkus.http.host=127.0.0.1 -Djava.lang.Integer.IntegerCache.high=10000 -Dvertx.disableHttpHeadersValidation=true -Dvertx.disableMetrics=true -Dvertx.disableH2c=true -Dvertx.disableWebsockets=true -Dvertx.flashPolicyHandler=false -Dvertx.threadChecks=false -Dvertx.disableContextTimings=true -Dvertx.disableTCCL=true -Dhibernate.allow_update_outside_transaction=true -Djboss.threads.eqe.statistics=false -jar target/pgclient-1.0-SNAPSHOT-runner.jar
+

+ 0 - 0
frameworks/Java/quarkus/hibernate/README.md → frameworks/Java/quarkus/resteasy-hibernate/README.md


+ 16 - 4
frameworks/Java/quarkus/hibernate/pom.xml → frameworks/Java/quarkus/resteasy-hibernate/pom.xml

@@ -10,16 +10,28 @@
     </parent>
     </parent>
 
 
     <groupId>io.quarkus.benchmark</groupId>
     <groupId>io.quarkus.benchmark</groupId>
-    <artifactId>hibernate</artifactId>
+    <artifactId>resteasy-hibernate</artifactId>
 
 
     <dependencies>
     <dependencies>
         <dependency>
         <dependency>
-            <groupId>io.quarkus.benchmark</groupId>
-            <artifactId>base</artifactId>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-hibernate-orm</artifactId>
         </dependency>
         </dependency>
         <dependency>
         <dependency>
             <groupId>io.quarkus</groupId>
             <groupId>io.quarkus</groupId>
-            <artifactId>quarkus-hibernate-orm</artifactId>
+            <artifactId>quarkus-scheduler</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-resteasy</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-resteasy-jackson</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-jdbc-postgresql</artifactId>
         </dependency>
         </dependency>
         <dependency>
         <dependency>
             <groupId>com.github.spullara.mustache.java</groupId>
             <groupId>com.github.spullara.mustache.java</groupId>

+ 3 - 0
frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/cdi/HibernateOrmNativeComponents.java → frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/cdi/HibernateOrmNativeComponents.java

@@ -1,6 +1,7 @@
 package io.quarkus.benchmark.cdi;
 package io.quarkus.benchmark.cdi;
 
 
 import javax.enterprise.inject.Produces;
 import javax.enterprise.inject.Produces;
+import javax.enterprise.inject.Typed;
 import javax.inject.Singleton;
 import javax.inject.Singleton;
 import javax.persistence.EntityManagerFactory;
 import javax.persistence.EntityManagerFactory;
 import javax.persistence.PersistenceUnit;
 import javax.persistence.PersistenceUnit;
@@ -13,6 +14,8 @@ public class HibernateOrmNativeComponents {
 	@PersistenceUnit
 	@PersistenceUnit
 	EntityManagerFactory entityManagerFactory;
 	EntityManagerFactory entityManagerFactory;
 
 
+	@Singleton
+	@Typed(SessionFactory.class)
 	@Produces
 	@Produces
 	SessionFactory extractSessionFactory() {
 	SessionFactory extractSessionFactory() {
 		return entityManagerFactory.unwrap( SessionFactory.class );
 		return entityManagerFactory.unwrap( SessionFactory.class );

+ 0 - 0
frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/filter/ServerHeaderFilter.java → frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/filter/ServerHeaderFilter.java


+ 56 - 0
frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/model/Fortune.java

@@ -0,0 +1,56 @@
+package io.quarkus.benchmark.model;
+
+import org.hibernate.annotations.Immutable;
+
+import java.util.Objects;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+
+@Entity
+@Immutable
+public class Fortune {
+
+    @Id
+    private int id;
+    private String message;
+
+    public Fortune() {}
+
+    public Fortune(int id, String message) {
+        this.id = id;
+        this.message = message;
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o)
+            return true;
+        if (o == null || getClass() != o.getClass())
+            return false;
+        Fortune fortune = (Fortune) o;
+        return id == fortune.id &&
+                Objects.equals(message, fortune.message);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(id, message);
+    }
+}

+ 29 - 0
frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/model/World.java

@@ -0,0 +1,29 @@
+package io.quarkus.benchmark.model;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+
+@Entity
+public class World {
+
+    @Id
+    private int id;
+    private int randomNumber;
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public int getRandomNumber() {
+        return randomNumber;
+    }
+
+    public void setRandomNumber(int randomNumber) {
+        this.randomNumber = randomNumber;
+    }
+
+}

+ 9 - 7
frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/repository/hibernate/FortuneRepository.java → frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/repository/FortuneRepository.java

@@ -1,17 +1,19 @@
-package io.quarkus.benchmark.repository.hibernate;
+package io.quarkus.benchmark.repository;
 
 
-import io.quarkus.benchmark.model.hibernate.Fortune;
-import org.hibernate.SessionFactory;
-import org.hibernate.StatelessSession;
+import java.util.List;
 
 
-import javax.enterprise.context.ApplicationScoped;
 import javax.inject.Inject;
 import javax.inject.Inject;
+import javax.inject.Singleton;
 import javax.persistence.criteria.CriteriaBuilder;
 import javax.persistence.criteria.CriteriaBuilder;
 import javax.persistence.criteria.CriteriaQuery;
 import javax.persistence.criteria.CriteriaQuery;
 import javax.persistence.criteria.Root;
 import javax.persistence.criteria.Root;
-import java.util.List;
 
 
-@ApplicationScoped
+import org.hibernate.SessionFactory;
+import org.hibernate.StatelessSession;
+
+import io.quarkus.benchmark.model.Fortune;
+
+@Singleton
 public class FortuneRepository {
 public class FortuneRepository {
 
 
     @Inject
     @Inject

+ 5 - 3
frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/repository/hibernate/WorldRepository.java → frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/repository/WorldRepository.java

@@ -1,20 +1,21 @@
-package io.quarkus.benchmark.repository.hibernate;
+package io.quarkus.benchmark.repository;
 
 
 import java.util.ArrayList;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collection;
 import java.util.Set;
 import java.util.Set;
 import java.util.concurrent.ThreadLocalRandom;
 import java.util.concurrent.ThreadLocalRandom;
-import java.util.stream.Collectors;
+
 import javax.inject.Inject;
 import javax.inject.Inject;
 import javax.inject.Singleton;
 import javax.inject.Singleton;
 import javax.transaction.Transactional;
 import javax.transaction.Transactional;
 
 
-import io.quarkus.benchmark.model.hibernate.World;
 import org.hibernate.FlushMode;
 import org.hibernate.FlushMode;
 import org.hibernate.Session;
 import org.hibernate.Session;
 import org.hibernate.SessionFactory;
 import org.hibernate.SessionFactory;
 import org.hibernate.StatelessSession;
 import org.hibernate.StatelessSession;
 
 
+import io.quarkus.benchmark.model.World;
+
 
 
 @Singleton
 @Singleton
 public class WorldRepository {
 public class WorldRepository {
@@ -46,6 +47,7 @@ public class WorldRepository {
         }
         }
     }
     }
 
 
+    @Transactional
     public void updateAll(Collection<World> worlds) {
     public void updateAll(Collection<World> worlds) {
         try (Session s = sf.openSession()) {
         try (Session s = sf.openSession()) {
             s.setJdbcBatchSize(worlds.size());
             s.setJdbcBatchSize(worlds.size());

+ 5 - 4
frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/resource/hibernate/DbResource.java → frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/resource/DbResource.java

@@ -1,12 +1,10 @@
-package io.quarkus.benchmark.resource.hibernate;
-
-import io.quarkus.benchmark.model.hibernate.World;
-import io.quarkus.benchmark.repository.hibernate.WorldRepository;
+package io.quarkus.benchmark.resource;
 
 
 import java.util.Collection;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.HashSet;
 import java.util.Set;
 import java.util.Set;
 import java.util.concurrent.ThreadLocalRandom;
 import java.util.concurrent.ThreadLocalRandom;
+
 import javax.inject.Inject;
 import javax.inject.Inject;
 import javax.inject.Singleton;
 import javax.inject.Singleton;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.Consumes;
@@ -16,6 +14,9 @@ import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.MediaType;
 
 
+import io.quarkus.benchmark.model.World;
+import io.quarkus.benchmark.repository.WorldRepository;
+
 
 
 @Singleton
 @Singleton
 @Path("/")
 @Path("/")

+ 7 - 6
frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/resource/hibernate/FortuneResource.java → frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/resource/FortuneResource.java

@@ -1,4 +1,4 @@
-package io.quarkus.benchmark.resource.hibernate;
+package io.quarkus.benchmark.resource;
 
 
 import java.io.StringWriter;
 import java.io.StringWriter;
 import java.util.ArrayList;
 import java.util.ArrayList;
@@ -6,8 +6,8 @@ import java.util.Collections;
 import java.util.Comparator;
 import java.util.Comparator;
 import java.util.List;
 import java.util.List;
 
 
-import javax.enterprise.context.ApplicationScoped;
 import javax.inject.Inject;
 import javax.inject.Inject;
+import javax.inject.Singleton;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.GET;
 import javax.ws.rs.GET;
 import javax.ws.rs.Path;
 import javax.ws.rs.Path;
@@ -17,12 +17,13 @@ import javax.ws.rs.core.MediaType;
 import com.github.mustachejava.DefaultMustacheFactory;
 import com.github.mustachejava.DefaultMustacheFactory;
 import com.github.mustachejava.Mustache;
 import com.github.mustachejava.Mustache;
 import com.github.mustachejava.MustacheFactory;
 import com.github.mustachejava.MustacheFactory;
-import io.quarkus.benchmark.model.hibernate.Fortune;
-import io.quarkus.benchmark.repository.hibernate.FortuneRepository;
 
 
-@ApplicationScoped
+import io.quarkus.benchmark.model.Fortune;
+import io.quarkus.benchmark.repository.FortuneRepository;
+
+@Singleton
 @Path("/")
 @Path("/")
-@Produces(MediaType.TEXT_HTML)
+@Produces(MediaType.TEXT_HTML+"; charset=UTF-8")
 @Consumes(MediaType.APPLICATION_JSON)
 @Consumes(MediaType.APPLICATION_JSON)
 public class FortuneResource {
 public class FortuneResource {
 
 

+ 2 - 5
frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/resource/JsonResource.java → frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/resource/JsonResource.java

@@ -4,18 +4,15 @@ import javax.ws.rs.GET;
 import javax.ws.rs.Path;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.MediaType;
-import java.util.Collections;
-import java.util.Map;
 
 
 @Path("/json")
 @Path("/json")
 public class JsonResource {
 public class JsonResource {
-    private static final String MESSAGE = "message";
     private static final String HELLO = "Hello, World!";
     private static final String HELLO = "Hello, World!";
 
 
     @GET
     @GET
     @Produces(MediaType.APPLICATION_JSON)
     @Produces(MediaType.APPLICATION_JSON)
-    public Map<String, String> json() {
-        return Collections.singletonMap( MESSAGE, HELLO );
+    public Message json() {
+        return new Message(HELLO);
     }
     }
 }
 }
 
 

+ 13 - 0
frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/resource/Message.java

@@ -0,0 +1,13 @@
+package io.quarkus.benchmark.resource;
+
+public class Message {
+  private final String message;
+
+  public Message(String message) {
+    this.message = message;
+  }
+
+  public String getMessage() {
+    return message;
+  }
+}

+ 0 - 0
frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/resource/PlaintextResource.java → frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/resource/PlaintextResource.java


+ 9 - 8
frameworks/Java/quarkus/hibernate/src/main/resources/application.properties → frameworks/Java/quarkus/resteasy-hibernate/src/main/resources/application.properties

@@ -1,15 +1,16 @@
 #Test preferQueryMode ? sendBufferSize ? receiveBufferSize ?
 #Test preferQueryMode ? sendBufferSize ? receiveBufferSize ?
 #disableColumnSanitiser requires lower case column names
 #disableColumnSanitiser requires lower case column names
-quarkus.datasource.url=jdbc:postgresql://tfb-database:5432/hello_world?loggerLevel=OFF&disableColumnSanitiser=true&assumeMinServerVersion=12&sslmode=disable
-%dev.quarkus.datasource.url=jdbc:postgresql://localhost:5432/hello_world?loggerLevel=OFF&disableColumnSanitiser=true&assumeMinServerVersion=12&sslmode=disable
-quarkus.datasource.driver=org.postgresql.Driver
+quarkus.datasource.db-kind=postgresql
 quarkus.datasource.username=benchmarkdbuser
 quarkus.datasource.username=benchmarkdbuser
 quarkus.datasource.password=benchmarkdbpass
 quarkus.datasource.password=benchmarkdbpass
-quarkus.datasource.transactions=disabled
-quarkus.datasource.detect-statement-leaks=false
-quarkus.datasource.max-size=64
-quarkus.datasource.min-size=16
-quarkus.datasource.initial-size=64
+quarkus.datasource.jdbc.url=jdbc:postgresql://tfb-database:5432/hello_world?loggerLevel=OFF&disableColumnSanitiser=true&assumeMinServerVersion=12&sslmode=disable
+%dev.quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/hello_world?loggerLevel=OFF&disableColumnSanitiser=true&assumeMinServerVersion=12&sslmode=disable
+quarkus.datasource.jdbc.driver=org.postgresql.Driver
+quarkus.datasource.jdbc.transactions=disabled
+quarkus.datasource.jdbc.detect-statement-leaks=false
+quarkus.datasource.jdbc.max-size=64
+quarkus.datasource.jdbc.min-size=16
+quarkus.datasource.jdbc.initial-size=64
 
 
 quarkus.log.console.enable=true
 quarkus.log.console.enable=true
 quarkus.log.console.level=INFO
 quarkus.log.console.level=INFO

+ 20 - 0
frameworks/Java/quarkus/resteasy-hibernate/src/main/resources/fortunes.mustache

@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Fortunes</title>
+</head>
+<body>
+<table>
+    <tr>
+        <th>id</th>
+        <th>message</th>
+    </tr>
+    {{#fortunes}}
+        <tr>
+            <td>{{id}}</td>
+            <td>{{message}}</td>
+        </tr>
+    {{/fortunes}}
+</table>
+</body>
+</html>

+ 0 - 0
frameworks/Java/quarkus/hibernate/src/main/resources/import.sql → frameworks/Java/quarkus/resteasy-hibernate/src/main/resources/import.sql


+ 0 - 0
frameworks/Java/quarkus/hibernate/start-app.sh → frameworks/Java/quarkus/resteasy-hibernate/start-app.sh


+ 51 - 0
frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/pom.xml

@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project>
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>io.quarkus</groupId>
+        <artifactId>benchmark</artifactId>
+        <version>1.0-SNAPSHOT</version>
+        <relativePath>../</relativePath>
+    </parent>
+
+    <groupId>io.quarkus.benchmark</groupId>
+    <artifactId>resteasy-reactive-hibernate-reactive</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-scheduler</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-reactive-pg-client</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-hibernate-reactive</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-resteasy-reactive</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-resteasy-reactive-jackson</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.vertx</groupId>
+            <artifactId>vertx-web-templ-rocker</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-transport-native-epoll</artifactId>
+            <classifier>linux-x86_64</classifier>
+        </dependency>
+        <dependency>
+            <groupId>com.github.spullara.mustache.java</groupId>
+            <artifactId>compiler</artifactId>
+            <version>0.9.6</version>
+        </dependency>
+    </dependencies>
+</project>

+ 33 - 0
frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/filter/ServerHeaderFilter.java

@@ -0,0 +1,33 @@
+package io.quarkus.benchmark.filter;
+
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+
+import javax.inject.Singleton;
+
+import org.jboss.resteasy.reactive.server.ServerResponseFilter;
+
+import io.quarkus.scheduler.Scheduled;
+import io.vertx.core.http.HttpHeaders;
+import io.vertx.core.http.HttpServerResponse;
+
+@Singleton
+public class ServerHeaderFilter {
+
+    private static final CharSequence SERVER_HEADER_NAME = HttpHeaders.createOptimized("Server");
+    private static final CharSequence SERVER_HEADER_VALUE = HttpHeaders.createOptimized("Quarkus");
+    private static final CharSequence DATE_HEADER_NAME = HttpHeaders.createOptimized("Date");
+    
+    private CharSequence date;
+
+    @Scheduled(every="1s")
+    void increment() {
+        date = HttpHeaders.createOptimized(DateTimeFormatter.RFC_1123_DATE_TIME.format(ZonedDateTime.now()));
+    }
+
+    @ServerResponseFilter
+    public void filter(HttpServerResponse response) {
+        response.putHeader(SERVER_HEADER_NAME, SERVER_HEADER_VALUE);
+        response.putHeader(DATE_HEADER_NAME, date);
+    }
+}

+ 56 - 0
frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/model/Fortune.java

@@ -0,0 +1,56 @@
+package io.quarkus.benchmark.model;
+
+import org.hibernate.annotations.Immutable;
+
+import java.util.Objects;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+
+@Entity
+@Immutable
+public class Fortune {
+
+    @Id
+    private int id;
+    private String message;
+
+    public Fortune() {}
+
+    public Fortune(int id, String message) {
+        this.id = id;
+        this.message = message;
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o)
+            return true;
+        if (o == null || getClass() != o.getClass())
+            return false;
+        Fortune fortune = (Fortune) o;
+        return id == fortune.id &&
+                Objects.equals(message, fortune.message);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(id, message);
+    }
+}

+ 29 - 0
frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/model/World.java

@@ -0,0 +1,29 @@
+package io.quarkus.benchmark.model;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+
+@Entity
+public class World {
+
+    @Id
+    private int id;
+    private int randomNumber;
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public int getRandomNumber() {
+        return randomNumber;
+    }
+
+    public void setRandomNumber(int randomNumber) {
+        this.randomNumber = randomNumber;
+    }
+
+}

+ 19 - 0
frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/repository/BaseRepository.java

@@ -0,0 +1,19 @@
+package io.quarkus.benchmark.repository;
+
+import java.util.function.Function;
+
+import javax.inject.Inject;
+
+import org.hibernate.reactive.mutiny.Mutiny;
+
+import io.smallrye.mutiny.Uni;
+
+public class BaseRepository {
+    @Inject
+    protected Mutiny.SessionFactory sf;
+
+    public <T> Uni<T> inSession(Function<Mutiny.Session, Uni<T>> work){
+        return sf.withSession(session -> work.apply(session));
+    }
+
+}

+ 25 - 0
frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/repository/FortuneRepository.java

@@ -0,0 +1,25 @@
+package io.quarkus.benchmark.repository;
+
+import java.util.List;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Root;
+
+import io.quarkus.benchmark.model.Fortune;
+import io.smallrye.mutiny.Uni;
+
+@ApplicationScoped
+public class FortuneRepository extends BaseRepository {
+
+    public Uni<List<Fortune>> findAll() {
+        return inSession(s -> {
+            CriteriaBuilder criteriaBuilder = sf.getCriteriaBuilder();
+            CriteriaQuery<Fortune> fortuneQuery = criteriaBuilder.createQuery(Fortune.class);
+            Root<Fortune> from = fortuneQuery.from(Fortune.class);
+            fortuneQuery.select(from);
+            return s.createQuery(fortuneQuery).getResultList();
+        });
+    }
+}

+ 65 - 0
frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/repository/WorldRepository.java

@@ -0,0 +1,65 @@
+package io.quarkus.benchmark.repository;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ThreadLocalRandom;
+
+import javax.inject.Singleton;
+
+import org.hibernate.reactive.mutiny.Mutiny;
+import org.hibernate.reactive.mutiny.Mutiny.Session;
+
+import io.quarkus.benchmark.model.World;
+import io.smallrye.mutiny.Uni;
+
+
+@Singleton
+public class WorldRepository extends BaseRepository {
+
+    /**
+     * This method is not required (nor specified) by the benchmark rules,
+     * but is quite handy to seed a local database and be able to experiment
+     * with the app locally.
+     */
+    public Uni<Void> createData() {
+        return inSession(s -> {
+            final ThreadLocalRandom random = ThreadLocalRandom.current();
+            int MAX = 10000;
+            Uni<Void>[] unis = new Uni[MAX];
+            for (int i=0; i<MAX; i++) {
+                final World world = new World();
+                world.setId(i + 1);
+                world.setRandomNumber(1 + random.nextInt(10000));
+                unis[i] = s.persist(world).map(v -> null);
+            }
+            return Uni.combine().all().unis(unis).combinedWith(l -> null)
+                    .flatMap(v -> s.flush())
+                    .map(v -> null);
+        });
+    }
+
+    public Uni<World> find(int id) {
+        return inSession(session -> singleFind(session, id));
+    }
+
+    public Uni<Collection<World>> update(Mutiny.Session s, Collection<World> worlds) {
+        return s.flush()
+                .map(v -> worlds);
+            }
+
+    public Uni<Collection<World>> find(Session s, Set<Integer> ids) {
+        //The rules require individual load: we can't use the Hibernate feature which allows load by multiple IDs as one single operation
+        ArrayList<Uni<World>> l = new ArrayList<>(ids.size());
+        for (Integer id : ids) {
+            l.add(singleFind(s, id));
+        }
+        return Uni.combine().all().unis(l).combinedWith(list -> (List<World>)list);
+    }
+
+    private static Uni<World> singleFind(final Mutiny.Session ss, final Integer id) {
+        return ss.find(World.class, id);
+    }
+
+}

+ 117 - 0
frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/resource/DbResource.java

@@ -0,0 +1,117 @@
+package io.quarkus.benchmark.resource;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.ThreadLocalRandom;
+
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+
+import org.hibernate.FlushMode;
+import org.hibernate.reactive.mutiny.Mutiny;
+
+import io.quarkus.benchmark.model.World;
+import io.quarkus.benchmark.repository.WorldRepository;
+import io.smallrye.mutiny.Uni;
+
+@Produces(MediaType.APPLICATION_JSON)
+@Path("/")
+public class DbResource {
+
+    @Inject
+    WorldRepository worldRepository;
+
+    @GET
+    @Path("db")
+    public Uni<World> db() {
+        return randomWorld();
+    }
+
+    @GET
+    @Path("queries")
+    public Uni<Collection<World>> queries(@QueryParam("queries") String queries) {
+        return worldRepository.inSession(session -> randomWorldForRead(session, parseQueryCount(queries)));
+    }
+
+    private Uni<Collection<World>> randomWorldForRead(Mutiny.Session session, int count) {
+        Set<Integer> ids = new HashSet<>(count);
+        int counter = 0;
+        while (counter < count) {
+            counter += ids.add(Integer.valueOf(randomWorldNumber())) ? 1 : 0;
+        }
+        return worldRepository.find(session, ids);
+    }
+
+    @GET
+    @Path("updates")
+    public Uni<Collection<World>> updates(@QueryParam("queries") String queries) {
+        return worldRepository.inSession(session -> {
+            // FIXME: not supported
+            //          session.setJdbcBatchSize(worlds.size());
+            session.setFlushMode(FlushMode.MANUAL);
+
+            var worlds = randomWorldForRead(session, parseQueryCount(queries));
+            return worlds.flatMap(worldsCollection -> {
+                worldsCollection.forEach( w -> {
+                    //Read the one field, as required by the following rule:
+                    // # vi. At least the randomNumber field must be read from the database result set.
+                    final int previousRead = w.getRandomNumber();
+                    //Update it, but make sure to exclude the current number as Hibernate optimisations would have us "fail"
+                    //the verification:
+                    w.setRandomNumber(randomWorldNumber(previousRead));
+                } );
+                
+                return worldRepository.update(session, worldsCollection);
+            });
+        });
+    }
+
+    private Uni<World> randomWorld() {
+        return worldRepository.find(randomWorldNumber());
+    }
+
+    private int randomWorldNumber() {
+        return 1 + ThreadLocalRandom.current().nextInt(10000);
+    }
+
+    /**
+     * Also according to benchmark requirements, except that in this special case
+     * of the update test we need to ensure we'll actually generate an update operation:
+     * for this we need to generate a random number between 1 to 10000, but different
+     * from the current field value.
+     * @param previousRead
+     * @return
+     */
+    private int randomWorldNumber(final int previousRead) {
+        //conceptually split the random space in those before previousRead,
+        //and those after: this approach makes sure to not affect the random characteristics.
+        final int trueRandom = ThreadLocalRandom.current().nextInt(9999) + 2;
+        if (trueRandom<=previousRead) {
+            //all figures equal or before the current field read need to be shifted back by one
+            //so to avoid hitting the same number while not affecting the distribution.
+            return trueRandom - 1;
+        }
+        else {
+            //Those after are generated by taking the generated value 2...10000 as is.
+            return trueRandom;
+        }
+    }
+
+    private int parseQueryCount(String textValue) {
+        if (textValue == null) {
+            return 1;
+        }
+        int parsedValue;
+        try {
+            parsedValue = Integer.parseInt(textValue);
+        } catch (NumberFormatException e) {
+            return 1;
+        }
+        return Math.min(500, Math.max(1, parsedValue));
+    }
+}

+ 47 - 0
frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/resource/FortuneResource.java

@@ -0,0 +1,47 @@
+package io.quarkus.benchmark.resource;
+
+import java.io.StringWriter;
+import java.util.Collections;
+import java.util.Comparator;
+
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+import com.github.mustachejava.DefaultMustacheFactory;
+import com.github.mustachejava.Mustache;
+import com.github.mustachejava.MustacheFactory;
+
+import io.quarkus.benchmark.model.Fortune;
+import io.quarkus.benchmark.repository.FortuneRepository;
+import io.smallrye.mutiny.Uni;
+
+@Path("/fortunes")
+public class FortuneResource  {
+
+    @Inject
+    FortuneRepository repository;
+    private Mustache template;
+    private Comparator<Fortune> fortuneComparator;
+
+
+    public FortuneResource() {
+        MustacheFactory mf = new DefaultMustacheFactory();
+        template = mf.compile("fortunes.mustache");
+        fortuneComparator = Comparator.comparing(fortune -> fortune.getMessage());
+    }
+
+    @Produces("text/html; charset=UTF-8")
+    @GET
+    public Uni<String> fortunes() {
+        return repository.findAll()
+                .map(fortunes -> {
+                    fortunes.add(new Fortune(0, "Additional fortune added at request time."));
+                    fortunes.sort(fortuneComparator);
+                    StringWriter writer = new StringWriter();
+                    template.execute(writer, Collections.singletonMap("fortunes", fortunes));
+                    return writer.toString();
+                });
+    }
+}

+ 19 - 0
frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/resource/JsonResource.java

@@ -0,0 +1,19 @@
+package io.quarkus.benchmark.resource;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+@Path("/json")
+public class JsonResource  {
+
+    private static final String HELLO = "Hello, World!";
+
+    @Produces(MediaType.APPLICATION_JSON)
+    @GET
+    public Message json() {
+        return new Message(HELLO);
+    }
+}
+

+ 13 - 0
frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/resource/Message.java

@@ -0,0 +1,13 @@
+package io.quarkus.benchmark.resource;
+
+public class Message {
+  private final String message;
+
+  public Message(String message) {
+    this.message = message;
+  }
+
+  public String getMessage() {
+    return message;
+  }
+}

+ 20 - 0
frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/resource/PlaintextResource.java

@@ -0,0 +1,20 @@
+package io.quarkus.benchmark.resource;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import io.vertx.core.buffer.Buffer;
+
+@Path("/plaintext")
+public class PlaintextResource {
+    private static final String HELLO_WORLD = "Hello, world!";
+    private static final Buffer HELLO_WORLD_BUFFER = Buffer.factory.directBuffer(HELLO_WORLD, "UTF-8");
+
+    @Produces(MediaType.TEXT_PLAIN)
+    @GET
+    public Buffer plaintext() {
+        return HELLO_WORLD_BUFFER;
+    }
+}

+ 20 - 0
frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/resources/application.properties

@@ -0,0 +1,20 @@
+quarkus.datasource.db-kind=postgresql
+quarkus.datasource.username=benchmarkdbuser
+quarkus.datasource.password=benchmarkdbpass
+#quarkus.datasource.max-size=64
+
+# Reactive config
+quarkus.datasource.reactive=true
+quarkus.datasource.reactive.url=postgresql://tfb-database:5432/hello_world
+%dev.quarkus.datasource.reactive.url=postgresql://localhost:5432/hello_world
+
+quarkus.datasource.reactive.thread-local=true
+quarkus.datasource.reactive.cache-prepared-statements=true
+quarkus.datasource.reactive.max-size=4
+
+#quarkus.vertx.storage=false
+
+quarkus.log.console.enable=true
+quarkus.log.console.level=INFO
+quarkus.log.file.enable=false
+quarkus.log.level=INFO

+ 20 - 0
frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/resources/fortunes.mustache

@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Fortunes</title>
+</head>
+<body>
+<table>
+    <tr>
+        <th>id</th>
+        <th>message</th>
+    </tr>
+    {{#fortunes}}
+        <tr>
+            <td>{{id}}</td>
+            <td>{{message}}</td>
+        </tr>
+    {{/fortunes}}
+</table>
+</body>
+</html>

+ 2 - 0
frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/start-app.sh

@@ -0,0 +1,2 @@
+java -XX:+FlightRecorder -XX:+UseParallelGC -Dquarkus.datasource.url=vertx-reactive:postgresql://localhost:5432/hello_world -Dquarkus.http.host=127.0.0.1 -Djava.lang.Integer.IntegerCache.high=10000 -Dvertx.disableHttpHeadersValidation=true -Dvertx.disableMetrics=true -Dvertx.disableH2c=true -Dvertx.disableWebsockets=true -Dvertx.flashPolicyHandler=false -Dvertx.threadChecks=false -Dvertx.disableContextTimings=true -Dvertx.disableTCCL=true -Dhibernate.allow_update_outside_transaction=true -Djboss.threads.eqe.statistics=false -jar target/pgclient-1.0-SNAPSHOT-runner.jar
+

+ 69 - 0
frameworks/Java/quarkus/resteasy-reactive-hibernate/README.md

@@ -0,0 +1,69 @@
+# Local development
+
+During development it might be easier to start a PostgreSQL instance directly:
+
+    sudo podman run --ulimit memlock=-1:-1 -it --rm=true --network host --memory-swappiness=0 --name HibernateTestingPGSQL -e POSTGRES_USER=benchmarkdbuser -e POSTGRES_PASSWORD=benchmarkdbpass -e POSTGRES_DB=hello_world -p 5432:5432 postgres:12
+
+Then edit the `application.properties` resource, so to point to the database on localhost.
+
+On first run make sure you set Hibernate to create the schema:
+
+    quarkus.hibernate-orm.database.generation=drop-and-create
+
+Build the application (might need to have installed the parent and dependencies first):
+
+    mvn clean package
+
+Run the application
+
+    ./start-app.sh
+
+If you just created the DB schema, you will need to create the test data. Hit this endpoint once:
+
+    http://127.0.0.1:8080/createdata
+
+Generate load on the application to test / profile it. I suggest to use `https://github.com/giltene/wrk2`.
+
+Example run, assuming you have built wrk2 in `~/sources/wrk2` :
+
+     ~/sources/wrk2/wrk -c 100 -d 60 -R 400 http://localhost:8080/db
+
+The URL `http://localhost:8080/db` represents one specific benchmark; there are several more to try
+but you will likely want to focus on them one at a time.
+
+
+## Test URLs
+
+### Plaintext Test
+
+    http://localhost:8080/plaintext
+
+### JSON Encoding Test
+
+    http://localhost:8080/json
+
+### Database Query Test
+
+    http://localhost:8080/db
+
+### Database Queries Test
+
+    http://localhost:8080/queries?queries=5
+
+### Database Update Test
+
+    http://localhost:8080/updates?queries=5
+
+### Template rendering Test
+
+    http://localhost:8080/fortunes
+
+## Full verification
+
+Use the main Techempower script in the root to run all official verifications:
+
+./tfb --type all --mode verify --test quarkus-hibernate
+
+## Run the benchmark
+
+./tfb --type all --mode benchmark --test quarkus-hibernate

+ 44 - 0
frameworks/Java/quarkus/resteasy-reactive-hibernate/pom.xml

@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project>
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>io.quarkus</groupId>
+        <artifactId>benchmark</artifactId>
+        <version>1.0-SNAPSHOT</version>
+        <relativePath>../</relativePath>
+    </parent>
+
+    <groupId>io.quarkus.benchmark</groupId>
+    <artifactId>resteasy-reactive-hibernate</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-hibernate-orm</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-scheduler</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-resteasy-reactive</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-resteasy-reactive-jackson</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-jdbc-postgresql</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.github.spullara.mustache.java</groupId>
+            <artifactId>compiler</artifactId>
+            <version>0.9.6</version>
+        </dependency>
+
+    </dependencies>
+
+</project>

+ 24 - 0
frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/cdi/HibernateOrmNativeComponents.java

@@ -0,0 +1,24 @@
+package io.quarkus.benchmark.cdi;
+
+import javax.enterprise.inject.Produces;
+import javax.enterprise.inject.Typed;
+import javax.inject.Singleton;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.PersistenceUnit;
+
+import org.hibernate.SessionFactory;
+
+@Singleton
+public class HibernateOrmNativeComponents {
+
+	@PersistenceUnit
+	EntityManagerFactory entityManagerFactory;
+
+	@Singleton
+	@Typed(SessionFactory.class)
+	@Produces
+	SessionFactory extractSessionFactory() {
+		return entityManagerFactory.unwrap( SessionFactory.class );
+	}
+
+}

+ 32 - 0
frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/filter/ServerHeaderFilter.java

@@ -0,0 +1,32 @@
+package io.quarkus.benchmark.filter;
+
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+
+import javax.inject.Singleton;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerResponseContext;
+import javax.ws.rs.container.ContainerResponseFilter;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.Provider;
+
+import io.quarkus.scheduler.Scheduled;
+
+@Singleton
+@Provider
+public class ServerHeaderFilter implements ContainerResponseFilter {
+
+    private String date;
+
+    @Scheduled(every="1s")
+    void increment() {
+        date = DateTimeFormatter.RFC_1123_DATE_TIME.format(ZonedDateTime.now());
+    }
+
+    @Override
+    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) {
+        final MultivaluedMap<String, Object> headers = responseContext.getHeaders();
+        headers.add( "Server", "Quarkus");
+        headers.add( "Date", date);
+    }
+}

+ 56 - 0
frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/model/Fortune.java

@@ -0,0 +1,56 @@
+package io.quarkus.benchmark.model;
+
+import org.hibernate.annotations.Immutable;
+
+import java.util.Objects;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+
+@Entity
+@Immutable
+public class Fortune {
+
+    @Id
+    private int id;
+    private String message;
+
+    public Fortune() {}
+
+    public Fortune(int id, String message) {
+        this.id = id;
+        this.message = message;
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o)
+            return true;
+        if (o == null || getClass() != o.getClass())
+            return false;
+        Fortune fortune = (Fortune) o;
+        return id == fortune.id &&
+                Objects.equals(message, fortune.message);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(id, message);
+    }
+}

+ 29 - 0
frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/model/World.java

@@ -0,0 +1,29 @@
+package io.quarkus.benchmark.model;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+
+@Entity
+public class World {
+
+    @Id
+    private int id;
+    private int randomNumber;
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public int getRandomNumber() {
+        return randomNumber;
+    }
+
+    public void setRandomNumber(int randomNumber) {
+        this.randomNumber = randomNumber;
+    }
+
+}

+ 31 - 0
frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/repository/FortuneRepository.java

@@ -0,0 +1,31 @@
+package io.quarkus.benchmark.repository;
+
+import java.util.List;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Root;
+
+import org.hibernate.SessionFactory;
+import org.hibernate.StatelessSession;
+
+import io.quarkus.benchmark.model.Fortune;
+
+@Singleton
+public class FortuneRepository {
+
+    @Inject
+    SessionFactory sf;
+
+    public List<Fortune> findAllStateless() {
+        try (StatelessSession s = sf.openStatelessSession()) {
+            CriteriaBuilder criteriaBuilder = sf.getCriteriaBuilder();
+            CriteriaQuery<Fortune> fortuneQuery = criteriaBuilder.createQuery(Fortune.class);
+            Root<Fortune> from = fortuneQuery.from(Fortune.class);
+            fortuneQuery.select(from);
+            return s.createQuery(fortuneQuery).getResultList();
+        }
+    }
+}

+ 77 - 0
frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/repository/WorldRepository.java

@@ -0,0 +1,77 @@
+package io.quarkus.benchmark.repository;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Set;
+import java.util.concurrent.ThreadLocalRandom;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import javax.transaction.Transactional;
+
+import org.hibernate.FlushMode;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.StatelessSession;
+
+import io.quarkus.benchmark.model.World;
+
+
+@Singleton
+public class WorldRepository {
+
+    @Inject
+    SessionFactory sf;
+
+    /**
+     * This method is not required (nor specified) by the benchmark rules,
+     * but is quite handy to seed a local database and be able to experiment
+     * with the app locally.
+     */
+    @Transactional
+    public void createData() {
+        try (StatelessSession statelessSession = sf.openStatelessSession()) {
+            final ThreadLocalRandom random = ThreadLocalRandom.current();
+            for (int i=1; i<=10000; i++) {
+                final World world = new World();
+                world.setId(i);
+                world.setRandomNumber(1 + random.nextInt(10000));
+                statelessSession.insert(world);
+            }
+        }
+    }
+
+    public World findSingleAndStateless(int id) {
+        try (StatelessSession ss = sf.openStatelessSession()) {
+            return singleStatelessWorldLoad(ss,id);
+        }
+    }
+
+    @Transactional
+    public void updateAll(Collection<World> worlds) {
+        try (Session s = sf.openSession()) {
+            s.setJdbcBatchSize(worlds.size());
+            s.setHibernateFlushMode(FlushMode.MANUAL);
+            for (World w : worlds) {
+                s.update(w);
+            }
+            s.flush();
+        }
+    }
+
+    public Collection<World> findReadonly(Set<Integer> ids) {
+        try (StatelessSession s = sf.openStatelessSession()) {
+            //The rules require individual load: we can't use the Hibernate feature which allows load by multiple IDs as one single operation
+            ArrayList l = new ArrayList<>(ids.size());
+            for (Integer id : ids) {
+                l.add(singleStatelessWorldLoad(s,id));
+            }
+            return l;
+        }
+    }
+
+    private static World singleStatelessWorldLoad(final StatelessSession ss, final Integer id) {
+        return (World) ss.get(World.class, id);
+    }
+
+}

+ 137 - 0
frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/resource/DbResource.java

@@ -0,0 +1,137 @@
+package io.quarkus.benchmark.resource;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.ThreadLocalRandom;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+
+import io.quarkus.benchmark.model.World;
+import io.quarkus.benchmark.repository.WorldRepository;
+import io.smallrye.common.annotation.Blocking;
+
+
+@Singleton
+@Path("/")
+@Produces(MediaType.APPLICATION_JSON)
+@Consumes(MediaType.APPLICATION_JSON)
+public class DbResource {
+
+    @Inject
+    WorldRepository worldRepository;
+
+    @Blocking
+    @GET
+    @Path("/db")
+    public World db() {
+        World world = randomWorldForRead();
+        if (world==null) throw new IllegalStateException( "No data found in DB. Did you seed the database? Make sure to invoke /createdata once." );
+        return world;
+    }
+
+    @Blocking
+    @GET
+    @Path("/queries")
+    public World[] queries(@QueryParam("queries") String queries) {
+        final int count = parseQueryCount(queries);
+        World[] worlds = randomWorldForRead(count).toArray(new World[0]);
+        return worlds;
+    }
+
+    @Blocking
+    @GET
+    @Path("/updates")
+    //Rules: https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Framework-Tests-Overview#database-updates
+    //N.B. the benchmark seems to be designed to get in deadlocks when using a "safe pattern" of updating
+    // the entity within the same transaction as the one which read it.
+    // We therefore need to do a "read then write" while relinquishing the transaction between the two operations, as
+    // all other tested frameworks seem to do.
+    public World[] updates(@QueryParam("queries") String queries) {
+        final int count = parseQueryCount(queries);
+        final Collection<World> worlds = randomWorldForRead(count);
+        worlds.forEach( w -> {
+            //Read the one field, as required by the following rule:
+            // # vi. At least the randomNumber field must be read from the database result set.
+            final int previousRead = w.getRandomNumber();
+            //Update it, but make sure to exclude the current number as Hibernate optimisations would have us "fail"
+            //the verification:
+            w.setRandomNumber(randomWorldNumber(previousRead));
+        } );
+        worldRepository.updateAll(worlds);
+        return worlds.toArray(new World[0]);
+    }
+
+    @Blocking
+    @GET
+    @Path( "/createdata" )
+    public String createData() {
+        worldRepository.createData();
+        return "OK";
+    }
+
+    private World randomWorldForRead() {
+        return worldRepository.findSingleAndStateless(randomWorldNumber());
+    }
+
+    private Collection<World> randomWorldForRead(int count) {
+        Set<Integer> ids = new HashSet<>(count);
+        int counter = 0;
+        while (counter < count) {
+            counter += ids.add(Integer.valueOf(randomWorldNumber())) ? 1 : 0;
+        }
+        return worldRepository.findReadonly(ids);
+    }
+
+    /**
+     * According to benchmark requirements
+     * @return returns a number from 1 to 10000
+     */
+    private int randomWorldNumber() {
+        return 1 + ThreadLocalRandom.current().nextInt(10000);
+    }
+
+
+    /**
+     * Also according to benchmark requirements, except that in this special case
+     * of the update test we need to ensure we'll actually generate an update operation:
+     * for this we need to generate a random number between 1 to 10000, but different
+     * from the current field value.
+     * @param previousRead
+     * @return
+     */
+    private int randomWorldNumber(final int previousRead) {
+        //conceptually split the random space in those before previousRead,
+        //and those after: this approach makes sure to not affect the random characteristics.
+        final int trueRandom = ThreadLocalRandom.current().nextInt(9999) + 2;
+        if (trueRandom<=previousRead) {
+            //all figures equal or before the current field read need to be shifted back by one
+            //so to avoid hitting the same number while not affecting the distribution.
+            return trueRandom - 1;
+        }
+        else {
+            //Those after are generated by taking the generated value 2...10000 as is.
+            return trueRandom;
+        }
+    }
+
+    private int parseQueryCount(String textValue) {
+        if (textValue == null) {
+            return 1;
+        }
+        int parsedValue;
+        try {
+            parsedValue = Integer.parseInt(textValue);
+        } catch (NumberFormatException e) {
+            return 1;
+        }
+        return Math.min(500, Math.max(1, parsedValue));
+    }
+}

+ 56 - 0
frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/resource/FortuneResource.java

@@ -0,0 +1,56 @@
+package io.quarkus.benchmark.resource;
+
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import com.github.mustachejava.DefaultMustacheFactory;
+import com.github.mustachejava.Mustache;
+import com.github.mustachejava.MustacheFactory;
+
+import io.quarkus.benchmark.model.Fortune;
+import io.quarkus.benchmark.repository.FortuneRepository;
+import io.smallrye.common.annotation.Blocking;
+
+@Singleton
+@Path("/")
+@Produces(MediaType.TEXT_HTML+"; charset=UTF-8")
+@Consumes(MediaType.APPLICATION_JSON)
+public class FortuneResource {
+
+    @Inject
+    FortuneRepository repository;
+
+    private final Mustache template;
+    private final Comparator<Fortune> fortuneComparator;
+
+    public FortuneResource() {
+        MustacheFactory mf = new DefaultMustacheFactory();
+        template = mf.compile("fortunes.mustache");
+        fortuneComparator = Comparator.comparing(fortune -> fortune.getMessage());
+    }
+
+    @Blocking
+    @GET
+    @Path("/fortunes")
+    public String fortunes() {
+        List<Fortune> fortunes = new ArrayList<>(repository.findAllStateless());
+        fortunes.add(new Fortune(0, "Additional fortune added at request time."));
+        fortunes.sort(fortuneComparator);
+
+        StringWriter writer = new StringWriter();
+        template.execute(writer, Collections.singletonMap("fortunes", fortunes));
+
+        return writer.toString();
+    }
+}

+ 18 - 0
frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/resource/JsonResource.java

@@ -0,0 +1,18 @@
+package io.quarkus.benchmark.resource;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+@Path("/json")
+public class JsonResource {
+    private static final String HELLO = "Hello, World!";
+
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    public Message json() {
+        return new Message(HELLO);
+    }
+}
+

+ 13 - 0
frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/resource/Message.java

@@ -0,0 +1,13 @@
+package io.quarkus.benchmark.resource;
+
+public class Message {
+  private final String message;
+
+  public Message(String message) {
+    this.message = message;
+  }
+
+  public String getMessage() {
+    return message;
+  }
+}

+ 17 - 0
frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/resource/PlaintextResource.java

@@ -0,0 +1,17 @@
+package io.quarkus.benchmark.resource;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+@Path("/plaintext")
+public class PlaintextResource {
+    private static final String HELLO = "Hello, World!";
+
+    @GET
+    @Produces(MediaType.TEXT_PLAIN)
+    public String plaintext() {
+        return HELLO;
+    }
+}

+ 30 - 0
frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/resources/application.properties

@@ -0,0 +1,30 @@
+#Test preferQueryMode ? sendBufferSize ? receiveBufferSize ?
+#disableColumnSanitiser requires lower case column names
+quarkus.datasource.db-kind=postgresql
+quarkus.datasource.username=benchmarkdbuser
+quarkus.datasource.password=benchmarkdbpass
+quarkus.datasource.jdbc.url=jdbc:postgresql://tfb-database:5432/hello_world?loggerLevel=OFF&disableColumnSanitiser=true&assumeMinServerVersion=12&sslmode=disable
+%dev.quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/hello_world?loggerLevel=OFF&disableColumnSanitiser=true&assumeMinServerVersion=12&sslmode=disable
+quarkus.datasource.jdbc.driver=org.postgresql.Driver
+quarkus.datasource.jdbc.transactions=disabled
+quarkus.datasource.jdbc.detect-statement-leaks=false
+quarkus.datasource.jdbc.max-size=64
+quarkus.datasource.jdbc.min-size=16
+quarkus.datasource.jdbc.initial-size=64
+
+quarkus.log.console.enable=true
+quarkus.log.console.level=INFO
+quarkus.log.file.enable=false
+quarkus.log.level=INFO
+
+# Fully disable Hibernate ORM statistics gathering::
+quarkus.log.category."org.hibernate.engine.internal.StatisticalLoggingSessionEventListener".level=WARN
+
+# To create the schema:
+%dev.quarkus.hibernate-orm.database.generation=drop-and-create
+%dev.quarkus.hibernate-orm.sql-load-script=import.sql
+quarkus.hibernate-orm.database.generation=validate
+quarkus.hibernate-orm.log.sql=false
+
+
+

+ 20 - 0
frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/resources/fortunes.mustache

@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Fortunes</title>
+</head>
+<body>
+<table>
+    <tr>
+        <th>id</th>
+        <th>message</th>
+    </tr>
+    {{#fortunes}}
+        <tr>
+            <td>{{id}}</td>
+            <td>{{message}}</td>
+        </tr>
+    {{/fortunes}}
+</table>
+</body>
+</html>

+ 1 - 0
frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/resources/import.sql

@@ -0,0 +1 @@
+INSERT INTO Fortune(id, message) VALUES (1, 'Test value One');

+ 1 - 0
frameworks/Java/quarkus/resteasy-reactive-hibernate/start-app.sh

@@ -0,0 +1 @@
+java -XX:+FlightRecorder -XX:+UseParallelGC -Dquarkus.datasource.url=jdbc:postgresql://localhost:5432/hello_world?loggerLevel=OFF\&disableColumnSanitiser=true\&assumeMinServerVersion=12\&sslmode=disable -Dquarkus.http.host=127.0.0.1 -Djava.lang.Integer.IntegerCache.high=10000 -Dvertx.disableHttpHeadersValidation=true -Dvertx.disableMetrics=true -Dvertx.disableH2c=true -Dvertx.disableWebsockets=true -Dvertx.flashPolicyHandler=false -Dvertx.threadChecks=false -Dvertx.disableContextTimings=true -Dvertx.disableTCCL=true -Dhibernate.allow_update_outside_transaction=true -Djboss.threads.eqe.statistics=false -jar target/hibernate-1.0-SNAPSHOT-runner.jar

+ 117 - 0
frameworks/Java/quarkus/resteasy-reactive-pgclient/.factorypath

@@ -0,0 +1,117 @@
+<factorypath>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/quarkus/quarkus-scheduler/999-SNAPSHOT/quarkus-scheduler-999-SNAPSHOT.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/com/cronutils/cron-utils/9.0.2/cron-utils-9.0.2.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/quarkus/quarkus-reactive-pg-client/999-SNAPSHOT/quarkus-reactive-pg-client-999-SNAPSHOT.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/quarkus/quarkus-reactive-datasource/999-SNAPSHOT/quarkus-reactive-datasource-999-SNAPSHOT.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/quarkus/quarkus-datasource/999-SNAPSHOT/quarkus-datasource-999-SNAPSHOT.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/quarkus/quarkus-datasource-common/999-SNAPSHOT/quarkus-datasource-common-999-SNAPSHOT.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/quarkus/quarkus-vault-spi/999-SNAPSHOT/quarkus-vault-spi-999-SNAPSHOT.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/quarkus/quarkus-vertx/999-SNAPSHOT/quarkus-vertx-999-SNAPSHOT.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/quarkus/quarkus-netty/999-SNAPSHOT/quarkus-netty-999-SNAPSHOT.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/netty/netty-codec/4.1.45.Final/netty-codec-4.1.45.Final.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/netty/netty-handler/4.1.45.Final/netty-handler-4.1.45.Final.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/quarkus/quarkus-vertx-core/999-SNAPSHOT/quarkus-vertx-core-999-SNAPSHOT.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/smallrye/reactive/smallrye-axle-generator/0.0.13/smallrye-axle-generator-0.0.13.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/reactivex/rxjava2/rxjava/2.2.19/rxjava-2.2.19.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/smallrye/reactive/smallrye-reactive-streams-operators/1.0.10/smallrye-reactive-streams-operators-1.0.10.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/org/eclipse/microprofile/reactive-streams-operators/microprofile-reactive-streams-operators-api/1.0/microprofile-reactive-streams-operators-api-1.0.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/org/eclipse/microprofile/reactive-streams-operators/microprofile-reactive-streams-operators-core/1.0/microprofile-reactive-streams-operators-core-1.0.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/org/reactivestreams/reactive-streams/1.0.3/reactive-streams-1.0.3.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/vertx/vertx-codegen/3.8.5/vertx-codegen-3.8.5.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/org/mvel/mvel2/2.3.1.Final/mvel2-2.3.1.Final.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/smallrye/reactive/smallrye-axle-core/0.0.13/smallrye-axle-core-0.0.13.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/vertx/vertx-rx-java2/3.8.5/vertx-rx-java2-3.8.5.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/vertx/vertx-rx-gen/3.8.5/vertx-rx-gen-3.8.5.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/quarkus/quarkus-mutiny/999-SNAPSHOT/quarkus-mutiny-999-SNAPSHOT.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/smallrye/reactive/mutiny/0.4.4/mutiny-0.4.4.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/quarkus/quarkus-smallrye-context-propagation/999-SNAPSHOT/quarkus-smallrye-context-propagation-999-SNAPSHOT.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/smallrye/smallrye-context-propagation/1.0.11/smallrye-context-propagation-1.0.11.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/smallrye/smallrye-context-propagation-api/1.0.11/smallrye-context-propagation-api-1.0.11.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/smallrye/reactive/mutiny-context-propagation/0.4.4/mutiny-context-propagation-0.4.4.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/smallrye/reactive/smallrye-reactive-converter-api/1.0.10/smallrye-reactive-converter-api-1.0.10.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/smallrye/reactive/smallrye-mutiny-vertx-core/0.0.13/smallrye-mutiny-vertx-core-0.0.13.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/smallrye/reactive/smallrye-mutiny-vertx-runtime/0.0.13/smallrye-mutiny-vertx-runtime-0.0.13.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/smallrye/reactive/vertx-mutiny-generator/0.0.13/vertx-mutiny-generator-0.0.13.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/vertx/vertx-pg-client/3.8.5/vertx-pg-client-3.8.5.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/vertx/vertx-core/3.8.5/vertx-core-3.8.5.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/netty/netty-common/4.1.45.Final/netty-common-4.1.45.Final.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/netty/netty-buffer/4.1.45.Final/netty-buffer-4.1.45.Final.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/netty/netty-transport/4.1.45.Final/netty-transport-4.1.45.Final.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/netty/netty-handler-proxy/4.1.45.Final/netty-handler-proxy-4.1.45.Final.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/netty/netty-codec-socks/4.1.45.Final/netty-codec-socks-4.1.45.Final.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/netty/netty-codec-http/4.1.45.Final/netty-codec-http-4.1.45.Final.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/netty/netty-codec-http2/4.1.45.Final/netty-codec-http2-4.1.45.Final.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/netty/netty-resolver/4.1.45.Final/netty-resolver-4.1.45.Final.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/netty/netty-resolver-dns/4.1.45.Final/netty-resolver-dns-4.1.45.Final.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/netty/netty-codec-dns/4.1.45.Final/netty-codec-dns-4.1.45.Final.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/vertx/vertx-sql-client/3.8.5/vertx-sql-client-3.8.5.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/smallrye/reactive/smallrye-axle-pg-client/0.0.13/smallrye-axle-pg-client-0.0.13.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/smallrye/reactive/smallrye-axle-sql-client/0.0.13/smallrye-axle-sql-client-0.0.13.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/smallrye/reactive/smallrye-mutiny-vertx-pg-client/0.0.13/smallrye-mutiny-vertx-pg-client-0.0.13.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/smallrye/reactive/smallrye-mutiny-vertx-sql-client/0.0.13/smallrye-mutiny-vertx-sql-client-0.0.13.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/quarkus/quarkus-resteasy/999-SNAPSHOT/quarkus-resteasy-999-SNAPSHOT.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/quarkus/quarkus-vertx-http/999-SNAPSHOT/quarkus-vertx-http-999-SNAPSHOT.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/quarkus/quarkus-development-mode-spi/999-SNAPSHOT/quarkus-development-mode-spi-999-SNAPSHOT.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/quarkus/security/quarkus-security/1.0.1.Final/quarkus-security-1.0.1.Final.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/jakarta/enterprise/jakarta.enterprise.cdi-api/2.0.2/jakarta.enterprise.cdi-api-2.0.2.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/jakarta/el/jakarta.el-api/3.0.3/jakarta.el-api-3.0.3.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/jakarta/interceptor/jakarta.interceptor-api/1.2.5/jakarta.interceptor-api-1.2.5.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/vertx/vertx-web/3.8.5/vertx-web-3.8.5.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/vertx/vertx-web-common/3.8.5/vertx-web-common-3.8.5.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/vertx/vertx-auth-common/3.8.5/vertx-auth-common-3.8.5.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/vertx/vertx-bridge-common/3.8.5/vertx-bridge-common-3.8.5.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/quarkus/quarkus-resteasy-server-common/999-SNAPSHOT/quarkus-resteasy-server-common-999-SNAPSHOT.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/org/jboss/resteasy/resteasy-core/4.5.3.Final/resteasy-core-4.5.3.Final.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/org/jboss/spec/javax/ws/rs/jboss-jaxrs-api_2.1_spec/2.0.1.Final/jboss-jaxrs-api_2.1_spec-2.0.1.Final.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/org/jboss/resteasy/resteasy-core-spi/4.5.3.Final/resteasy-core-spi-4.5.3.Final.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/org/eclipse/microprofile/config/microprofile-config-api/1.4/microprofile-config-api-1.4.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/com/sun/activation/jakarta.activation/1.2.1/jakarta.activation-1.2.1.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/jakarta/validation/jakarta.validation-api/2.0.2/jakarta.validation-api-2.0.2.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/quarkus/quarkus-resteasy-jackson/999-SNAPSHOT/quarkus-resteasy-jackson-999-SNAPSHOT.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/quarkus/quarkus-jackson/999-SNAPSHOT/quarkus-jackson-999-SNAPSHOT.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/com/fasterxml/jackson/core/jackson-databind/2.10.3/jackson-databind-2.10.3.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/com/fasterxml/jackson/datatype/jackson-datatype-jsr310/2.10.3/jackson-datatype-jsr310-2.10.3.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/com/fasterxml/jackson/datatype/jackson-datatype-jdk8/2.10.3/jackson-datatype-jdk8-2.10.3.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/com/fasterxml/jackson/module/jackson-module-parameter-names/2.10.3/jackson-module-parameter-names-2.10.3.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/org/jboss/resteasy/resteasy-jackson2-provider/4.5.3.Final/resteasy-jackson2-provider-4.5.3.Final.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/org/jboss/resteasy/resteasy-jaxb-provider/4.5.3.Final/resteasy-jaxb-provider-4.5.3.Final.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/org/glassfish/jaxb/jaxb-runtime/2.3.3-b02/jaxb-runtime-2.3.3-b02.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/org/glassfish/jaxb/txw2/2.3.3-b02/txw2-2.3.3-b02.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/com/sun/istack/istack-commons-runtime/3.0.10/istack-commons-runtime-3.0.10.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/com/fasterxml/jackson/core/jackson-core/2.10.3/jackson-core-2.10.3.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/com/fasterxml/jackson/core/jackson-annotations/2.10.3/jackson-annotations-2.10.3.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/com/fasterxml/jackson/jaxrs/jackson-jaxrs-json-provider/2.10.3/jackson-jaxrs-json-provider-2.10.3.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/com/fasterxml/jackson/jaxrs/jackson-jaxrs-base/2.10.3/jackson-jaxrs-base-2.10.3.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/com/fasterxml/jackson/module/jackson-module-jaxb-annotations/2.10.3/jackson-module-jaxb-annotations-2.10.3.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/jakarta/activation/jakarta.activation-api/1.2.1/jakarta.activation-api-1.2.1.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/com/github/fge/json-patch/1.9/json-patch-1.9.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/com/github/fge/jackson-coreutils/1.6/jackson-coreutils-1.6.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/com/github/fge/msg-simple/1.1/msg-simple-1.1.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/com/github/fge/btf/1.2/btf-1.2.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/com/google/guava/guava/27.0.1-jre/guava-27.0.1-jre.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/com/google/guava/failureaccess/1.0.1/failureaccess-1.0.1.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/org/jboss/logging/jboss-logging/3.3.2.Final/jboss-logging-3.3.2.Final.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/org/jboss/spec/javax/xml/bind/jboss-jaxb-api_2.3_spec/2.0.0.Final/jboss-jaxb-api_2.3_spec-2.0.0.Final.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/quarkus/quarkus-arc/999-SNAPSHOT/quarkus-arc-999-SNAPSHOT.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/quarkus/arc/arc/999-SNAPSHOT/arc-999-SNAPSHOT.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/jakarta/annotation/jakarta.annotation-api/1.3.5/jakarta.annotation-api-1.3.5.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/jakarta/transaction/jakarta.transaction-api/1.3.3/jakarta.transaction-api-1.3.3.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/quarkus/quarkus-core/999-SNAPSHOT/quarkus-core-999-SNAPSHOT.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/jakarta/inject/jakarta.inject-api/1.0/jakarta.inject-api-1.0.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/quarkus/quarkus-ide-launcher/999-SNAPSHOT/quarkus-ide-launcher-999-SNAPSHOT.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/smallrye/config/smallrye-config/1.7.0/smallrye-config-1.7.0.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/smallrye/config/smallrye-config-common/1.7.0/smallrye-config-common-1.7.0.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/org/jboss/logmanager/jboss-logmanager-embedded/1.0.4/jboss-logmanager-embedded-1.0.4.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/org/jboss/logging/jboss-logging-annotations/2.1.0.Final/jboss-logging-annotations-2.1.0.Final.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/org/jboss/threads/jboss-threads/3.0.1.Final/jboss-threads-3.0.1.Final.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/org/slf4j/slf4j-api/1.7.30/slf4j-api-1.7.30.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/org/jboss/slf4j/slf4j-jboss-logging/1.2.0.Final/slf4j-jboss-logging-1.2.0.Final.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/org/graalvm/sdk/graal-sdk/19.3.1/graal-sdk-19.3.1.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/org/wildfly/common/wildfly-common/1.5.4.Final-format-001/wildfly-common-1.5.4.Final-format-001.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/org/eclipse/microprofile/context-propagation/microprofile-context-propagation-api/1.0.1/microprofile-context-propagation-api-1.0.1.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/io/quarkus/quarkus-jdbc-postgresql/999-SNAPSHOT/quarkus-jdbc-postgresql-999-SNAPSHOT.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/org/postgresql/postgresql/42.2.12/postgresql-42.2.12.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="VARJAR" id="M2_REPO/com/github/spullara/mustache/java/compiler/0.9.6/compiler-0.9.6.jar" enabled="true" runInBatchMode="false"/>
+    <factorypathentry kind="PLUGIN" id="org.eclipse.jst.ws.annotations.core" enabled="false" runInBatchMode="false"/>
+</factorypath>

+ 47 - 0
frameworks/Java/quarkus/resteasy-reactive-pgclient/pom.xml

@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project>
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>io.quarkus</groupId>
+        <artifactId>benchmark</artifactId>
+        <version>1.0-SNAPSHOT</version>
+        <relativePath>../</relativePath>
+    </parent>
+
+    <groupId>io.quarkus.benchmark</groupId>
+    <artifactId>resteasy-reactive-pgclient</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-scheduler</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-reactive-pg-client</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-resteasy-reactive</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-resteasy-reactive-jackson</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.vertx</groupId>
+            <artifactId>vertx-web-templ-rocker</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-transport-native-epoll</artifactId>
+            <classifier>linux-x86_64</classifier>
+        </dependency>
+        <dependency>
+            <groupId>com.github.spullara.mustache.java</groupId>
+            <artifactId>compiler</artifactId>
+            <version>0.9.6</version>
+        </dependency>
+    </dependencies>
+</project>

+ 33 - 0
frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/java/io/quarkus/benchmark/filter/ServerHeaderFilter.java

@@ -0,0 +1,33 @@
+package io.quarkus.benchmark.filter;
+
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+
+import javax.inject.Singleton;
+
+import org.jboss.resteasy.reactive.server.ServerResponseFilter;
+
+import io.quarkus.scheduler.Scheduled;
+import io.vertx.core.http.HttpHeaders;
+import io.vertx.core.http.HttpServerResponse;
+
+@Singleton
+public class ServerHeaderFilter {
+
+    private static final CharSequence SERVER_HEADER_NAME = HttpHeaders.createOptimized("Server");
+    private static final CharSequence SERVER_HEADER_VALUE = HttpHeaders.createOptimized("Quarkus");
+    private static final CharSequence DATE_HEADER_NAME = HttpHeaders.createOptimized("Date");
+    
+    private CharSequence date;
+
+    @Scheduled(every="1s")
+    void increment() {
+        date = HttpHeaders.createOptimized(DateTimeFormatter.RFC_1123_DATE_TIME.format(ZonedDateTime.now()));
+    }
+
+    @ServerResponseFilter
+    public void filter(HttpServerResponse response) {
+        response.putHeader(SERVER_HEADER_NAME, SERVER_HEADER_VALUE);
+        response.putHeader(DATE_HEADER_NAME, date);
+    }
+}

+ 48 - 0
frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/java/io/quarkus/benchmark/model/Fortune.java

@@ -0,0 +1,48 @@
+package io.quarkus.benchmark.model;
+
+import java.util.Objects;
+
+public class Fortune {
+
+    private int id;
+    private String message;
+
+    public Fortune() {}
+
+    public Fortune(int id, String message) {
+        this.id = id;
+        this.message = message;
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o)
+            return true;
+        if (o == null || getClass() != o.getClass())
+            return false;
+        Fortune fortune = (Fortune) o;
+        return id == fortune.id &&
+                Objects.equals(message, fortune.message);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(id, message);
+    }
+}

+ 35 - 0
frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/java/io/quarkus/benchmark/model/World.java

@@ -0,0 +1,35 @@
+package io.quarkus.benchmark.model;
+
+public class World implements Comparable<World>{
+
+    private int id;
+    private int randomNumber;
+
+    public World() {}
+
+    public World(int id, int randomNumber) {
+        this.id = id;
+        this.randomNumber = randomNumber;
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public int getRandomNumber() {
+        return randomNumber;
+    }
+
+    public void setRandomNumber(int randomNumber) {
+        this.randomNumber = randomNumber;
+    }
+
+    @Override
+    public int compareTo(World o) {
+        return Integer.compare(id, o.id);
+    }
+}

+ 30 - 0
frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/java/io/quarkus/benchmark/repository/FortuneRepository.java

@@ -0,0 +1,30 @@
+package io.quarkus.benchmark.repository;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+
+import io.quarkus.benchmark.model.Fortune;
+import io.smallrye.mutiny.Uni;
+import io.vertx.mutiny.sqlclient.Row;
+
+@ApplicationScoped
+public class FortuneRepository {
+
+    @Inject
+    PgClients clients;
+
+    public Uni<List<Fortune>> findAll() {
+        return clients.getClient().preparedQuery("SELECT * FROM Fortune" )
+                .execute()
+                .map(rowset -> {
+                    List<Fortune> ret = new ArrayList<>(rowset.size()+1);
+                    for(Row r : rowset) {
+                        ret.add(new Fortune(r.getInteger("id"), r.getString("message")));
+                    }
+                    return ret;
+                });
+    }
+}

+ 56 - 0
frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/java/io/quarkus/benchmark/repository/PgClientFactory.java

@@ -0,0 +1,56 @@
+package io.quarkus.benchmark.repository;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.inject.Produces;
+import javax.inject.Inject;
+
+import org.eclipse.microprofile.config.inject.ConfigProperty;
+
+import io.vertx.mutiny.core.Vertx;
+import io.vertx.mutiny.pgclient.PgPool;
+import io.vertx.pgclient.PgConnectOptions;
+import io.vertx.sqlclient.PoolOptions;
+
+@ApplicationScoped
+public class PgClientFactory {
+
+    // vertx-reactive:postgresql://tfb-database:5432/hello_world
+    private static final String PG_URI_MATCHER = "vertx-reactive:postgresql://([-a-zA-Z]+):([0-9]+)/(.*)";
+
+    @ConfigProperty(name = "quarkus.datasource.url")
+	String url;
+
+	@ConfigProperty(name = "quarkus.datasource.username")
+	String user;
+
+	@ConfigProperty(name = "quarkus.datasource.password")
+	String pass;
+
+	@Inject
+	Vertx vertx;
+
+	@Produces
+	@ApplicationScoped
+	public PgClients pgClients() {
+	    return new PgClients(this);
+	}
+
+
+	PgPool sqlClient(int size) {
+		PoolOptions options = new PoolOptions();
+		PgConnectOptions connectOptions = new PgConnectOptions();
+		Matcher matcher = Pattern.compile(PG_URI_MATCHER).matcher(url);
+		matcher.matches();
+		connectOptions.setDatabase(matcher.group(3));
+		connectOptions.setHost(matcher.group(1));
+		connectOptions.setPort(Integer.parseInt(matcher.group(2)));
+		connectOptions.setUser(user);
+		connectOptions.setPassword(pass);
+		connectOptions.setCachePreparedStatements(true);
+		options.setMaxSize(size);
+		return PgPool.pool(vertx, connectOptions, options);
+	}
+}

Some files were not shown because too many files changed in this diff