diff --git a/frameworks/Java/quarkus/README.md b/frameworks/Java/quarkus/README.md index 317a4be1aa5..899ca69a984 100644 --- a/frameworks/Java/quarkus/README.md +++ b/frameworks/Java/quarkus/README.md @@ -4,24 +4,19 @@ This is the Quarkus portion of a [benchmarking test suite](../) comparing a vari ## 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 * [Java OpenJDK 11](http://openjdk.java.net/) -* [Quarkus 1.1.1](https://quarkus.io) +* [Quarkus 1.11.0.Beta1](https://quarkus.io) ## Test URLs diff --git a/frameworks/Java/quarkus/base/pom.xml b/frameworks/Java/quarkus/base/pom.xml deleted file mode 100644 index e25d2214540..00000000000 --- a/frameworks/Java/quarkus/base/pom.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - 4.0.0 - - - io.quarkus - benchmark - 1.0-SNAPSHOT - ../ - - - io.quarkus.benchmark - base - - - - io.quarkus - quarkus-scheduler - - - - - - - org.jboss.jandex - jandex-maven-plugin - 1.0.7 - - - make-index - - jandex - - - - - - - - diff --git a/frameworks/Java/quarkus/benchmark_config.json b/frameworks/Java/quarkus/benchmark_config.json index 6fe21b23483..faed66a8183 100644 --- a/frameworks/Java/quarkus/benchmark_config.json +++ b/frameworks/Java/quarkus/benchmark_config.json @@ -21,11 +21,34 @@ "webserver": "Undertow", "os": "Linux", "database_os": "Linux", - "display_name": "Quarkus + Hibernate ORM", + "display_name": "Quarkus + RESTEasy + Hibernate ORM", "notes": "", "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", "db_url": "/db", "query_url": "/queries?queries=", @@ -40,11 +63,80 @@ "language": "Java", "flavor": "None", "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", "database_os": "Linux", - "display_name": "quarkus-pgclient", + "display_name": "Quarkus RESTEasy Reactive + Hibernate Reactive", "notes": "", "versus": "Netty" } diff --git a/frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/resource/pgclient/FortuneResource.java b/frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/resource/pgclient/FortuneResource.java deleted file mode 100644 index 7597c085c2a..00000000000 --- a/frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/resource/pgclient/FortuneResource.java +++ /dev/null @@ -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)); - } -} diff --git a/frameworks/Java/quarkus/pgclient/src/main/resources/templates/Fortunes.rocker.html b/frameworks/Java/quarkus/pgclient/src/main/resources/templates/Fortunes.rocker.html deleted file mode 100644 index c3cf547f319..00000000000 --- a/frameworks/Java/quarkus/pgclient/src/main/resources/templates/Fortunes.rocker.html +++ /dev/null @@ -1,21 +0,0 @@ -@import java.util.* -@import io.quarkus.benchmark.model.* -@args(List fortunes) - - -Fortunes - - - - - - - @for ((ForIterator i, Fortune fortune) : fortunes) { - - - - - } -
idmessage
@fortune.getId()@fortune.getMessage()
- - diff --git a/frameworks/Java/quarkus/pom.xml b/frameworks/Java/quarkus/pom.xml index a7d9e7cd0f1..792344c0fb9 100644 --- a/frameworks/Java/quarkus/pom.xml +++ b/frameworks/Java/quarkus/pom.xml @@ -8,16 +8,19 @@ pom - 1.5.2.Final + 1.11.0.Beta1 UTF-8 11 11 - base - hibernate - pgclient + resteasy-hibernate + reactive-routes-hibernate-reactive + reactive-routes-pgclient + resteasy-reactive-pgclient + resteasy-reactive-hibernate + resteasy-reactive-hibernate-reactive @@ -34,28 +37,24 @@ base ${project.version} + + io.vertx + vertx-pg-client + 3.9.0 + + + io.vertx + vertx-sql-client + 3.9.0 + + + io.vertx + vertx-web + 3.9.3 + - - - io.quarkus - quarkus-resteasy - - - io.quarkus - quarkus-resteasy-jackson - - - io.quarkus - quarkus-arc - - - io.quarkus - quarkus-jdbc-postgresql - - - @@ -90,6 +89,11 @@ + + io.quarkus + quarkus-bootstrap-maven-plugin + ${quarkus.version} + diff --git a/frameworks/Java/quarkus/quarkus-reactive-routes-hibernate-reactive.dockerfile b/frameworks/Java/quarkus/quarkus-reactive-routes-hibernate-reactive.dockerfile new file mode 100644 index 00000000000..3673b27f988 --- /dev/null +++ b/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"] diff --git a/frameworks/Java/quarkus/quarkus-pgclient.dockerfile b/frameworks/Java/quarkus/quarkus-reactive-routes-pgclient.dockerfile similarity index 55% rename from frameworks/Java/quarkus/quarkus-pgclient.dockerfile rename to frameworks/Java/quarkus/quarkus-reactive-routes-pgclient.dockerfile index 67b2141f84d..a2c818db68e 100644 --- a/frameworks/Java/quarkus/quarkus-pgclient.dockerfile +++ b/frameworks/Java/quarkus/quarkus-reactive-routes-pgclient.dockerfile @@ -1,18 +1,28 @@ FROM maven:3.6.3-jdk-11-slim as maven WORKDIR /quarkus +ENV MODULE=reactive-routes-pgclient + 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 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"] diff --git a/frameworks/Java/quarkus/quarkus-resteasy-reactive-hibernate-reactive.dockerfile b/frameworks/Java/quarkus/quarkus-resteasy-reactive-hibernate-reactive.dockerfile new file mode 100644 index 00000000000..cfe13c666ae --- /dev/null +++ b/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"] diff --git a/frameworks/Java/quarkus/quarkus-resteasy-reactive-hibernate.dockerfile b/frameworks/Java/quarkus/quarkus-resteasy-reactive-hibernate.dockerfile new file mode 100644 index 00000000000..cd718579906 --- /dev/null +++ b/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"] diff --git a/frameworks/Java/quarkus/quarkus-resteasy-reactive-pgclient.dockerfile b/frameworks/Java/quarkus/quarkus-resteasy-reactive-pgclient.dockerfile new file mode 100644 index 00000000000..a08a8de190f --- /dev/null +++ b/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"] diff --git a/frameworks/Java/quarkus/quarkus.dockerfile b/frameworks/Java/quarkus/quarkus.dockerfile index e32d6be7407..39bc4931343 100644 --- a/frameworks/Java/quarkus/quarkus.dockerfile +++ b/frameworks/Java/quarkus/quarkus.dockerfile @@ -1,18 +1,28 @@ FROM maven:3.6.3-jdk-11-slim as maven WORKDIR /quarkus +ENV MODULE=resteasy-hibernate + 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 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"] diff --git a/frameworks/Java/quarkus/reactive-routes-hibernate-reactive/pom.xml b/frameworks/Java/quarkus/reactive-routes-hibernate-reactive/pom.xml new file mode 100644 index 00000000000..c955632ae41 --- /dev/null +++ b/frameworks/Java/quarkus/reactive-routes-hibernate-reactive/pom.xml @@ -0,0 +1,46 @@ + + + 4.0.0 + + + io.quarkus + benchmark + 1.0-SNAPSHOT + ../ + + + io.quarkus.benchmark + reactive-routes-hibernate-reactive + + + + io.quarkus + quarkus-reactive-pg-client + + + io.quarkus + quarkus-scheduler + + + io.quarkus + quarkus-hibernate-reactive + + + io.quarkus + quarkus-vertx-web + + + com.github.spullara.mustache.java + compiler + 0.9.6 + + + io.vertx + vertx-pg-client + + + io.vertx + vertx-sql-client + + + diff --git a/frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/resource/pgclient/ServerHeaderFilter.java b/frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/filter/ServerHeaderFilter.java similarity index 92% rename from frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/resource/pgclient/ServerHeaderFilter.java rename to frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/filter/ServerHeaderFilter.java index 85a11a802dd..c46279cc783 100644 --- a/frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/resource/pgclient/ServerHeaderFilter.java +++ b/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.format.DateTimeFormatter; diff --git a/frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/model/hibernate/Fortune.java b/frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/model/Fortune.java similarity index 95% rename from frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/model/hibernate/Fortune.java rename to frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/model/Fortune.java index 8180aa312d1..5228080b02b 100644 --- a/frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/model/hibernate/Fortune.java +++ b/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; diff --git a/frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/model/hibernate/World.java b/frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/model/World.java similarity index 90% rename from frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/model/hibernate/World.java rename to frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/model/World.java index e49b245ba46..a9a2acc4a82 100644 --- a/frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/model/hibernate/World.java +++ b/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.Id; diff --git a/frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/repository/BaseRepository.java b/frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/repository/BaseRepository.java new file mode 100644 index 00000000000..8cc1e2e9a01 --- /dev/null +++ b/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 Uni inSession(Function> work){ + return sf.withSession(session -> work.apply(session)); + } + +} diff --git a/frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/repository/FortuneRepository.java b/frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/repository/FortuneRepository.java new file mode 100644 index 00000000000..a34254a0825 --- /dev/null +++ b/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> findAll() { + return inSession(s -> { + CriteriaBuilder criteriaBuilder = sf.getCriteriaBuilder(); + CriteriaQuery fortuneQuery = criteriaBuilder.createQuery(Fortune.class); + Root from = fortuneQuery.from(Fortune.class); + fortuneQuery.select(from); + return s.createQuery(fortuneQuery).getResultList(); + }); + } +} diff --git a/frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/repository/WorldRepository.java b/frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/repository/WorldRepository.java new file mode 100644 index 00000000000..bc236b0e4ca --- /dev/null +++ b/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 createData() { + return inSession(s -> { + final ThreadLocalRandom random = ThreadLocalRandom.current(); + int MAX = 10000; + Uni[] unis = new Uni[MAX]; + for (int i=0; i null); + } + return Uni.combine().all().unis(unis).combinedWith(l -> null) + .flatMap(v -> s.flush()) + .map(v -> null); + }); + } + + public Uni find(int id) { + return inSession(session -> singleFind(session, id)); + } + + public Uni> update(Mutiny.Session s, Collection worlds) { + return s.flush() + .map(v -> worlds); + } + + public Uni> find(Session s, Set ids) { + //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(singleFind(s, id)); + } + return Uni.combine().all().unis(l).combinedWith(list -> (List)list); + } + + private static Uni singleFind(final Mutiny.Session ss, final Integer id) { + return ss.find(World.class, id); + } + +} diff --git a/frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/resource/BaseResource.java b/frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/resource/BaseResource.java new file mode 100644 index 00000000000..b9ba205a368 --- /dev/null +++ b/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; + } + +} diff --git a/frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/resource/DbResource.java b/frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/resource/DbResource.java new file mode 100644 index 00000000000..70ccb75946b --- /dev/null +++ b/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> randomWorldForRead(Mutiny.Session session, int count) { + Set 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 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)); + } +} \ No newline at end of file diff --git a/frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/resource/FortuneResource.java b/frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/resource/FortuneResource.java new file mode 100644 index 00000000000..d430ef31122 --- /dev/null +++ b/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 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)); + } +} diff --git a/frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/resource/JsonResource.java b/frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/resource/JsonResource.java new file mode 100644 index 00000000000..9d932a13639 --- /dev/null +++ b/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 )); + } +} + diff --git a/frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/resource/pgclient/PlaintextResource.java b/frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/resource/PlaintextResource.java similarity index 70% rename from frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/resource/pgclient/PlaintextResource.java rename to frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/java/io/quarkus/benchmark/resource/PlaintextResource.java index 639c90e915b..c8649b551c2 100644 --- a/frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/resource/pgclient/PlaintextResource.java +++ b/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 io.quarkus.vertx.web.Route; -import io.vertx.core.buffer.Buffer; import io.vertx.ext.web.RoutingContext; @ApplicationScoped public class PlaintextResource { - private static final Buffer HELLO = Buffer.buffer("Hello, World!"); + private static final String HELLO = "Hello, World!"; @Route(path = "plaintext") public void plaintext(RoutingContext rc) { diff --git a/frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/resources/application.properties b/frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/resources/application.properties new file mode 100644 index 00000000000..18e5ae2367b --- /dev/null +++ b/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 \ No newline at end of file diff --git a/frameworks/Java/quarkus/base/src/main/resources/fortunes.mustache b/frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/resources/fortunes.mustache similarity index 100% rename from frameworks/Java/quarkus/base/src/main/resources/fortunes.mustache rename to frameworks/Java/quarkus/reactive-routes-hibernate-reactive/src/main/resources/fortunes.mustache diff --git a/frameworks/Java/quarkus/pgclient/start-app.sh b/frameworks/Java/quarkus/reactive-routes-hibernate-reactive/start-app.sh similarity index 100% rename from frameworks/Java/quarkus/pgclient/start-app.sh rename to frameworks/Java/quarkus/reactive-routes-hibernate-reactive/start-app.sh diff --git a/frameworks/Java/quarkus/pgclient/pom.xml b/frameworks/Java/quarkus/reactive-routes-pgclient/pom.xml similarity index 51% rename from frameworks/Java/quarkus/pgclient/pom.xml rename to frameworks/Java/quarkus/reactive-routes-pgclient/pom.xml index 6e92cb1eaa2..d9425b9128d 100644 --- a/frameworks/Java/quarkus/pgclient/pom.xml +++ b/frameworks/Java/quarkus/reactive-routes-pgclient/pom.xml @@ -10,12 +10,12 @@ io.quarkus.benchmark - pgclient + reactive-routes-pgclient - io.quarkus.benchmark - base + io.quarkus + quarkus-scheduler io.quarkus @@ -34,28 +34,10 @@ netty-transport-native-epoll linux-x86_64 + + com.github.spullara.mustache.java + compiler + 0.9.6 + - - - - com.fizzed - rocker-maven-plugin - 1.3.0 - - - generate-rocker-templates - generate-sources - - generate - - - ${project.basedir}/src/main/resources - true - - - - - - - diff --git a/frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/filter/ServerHeaderFilter.java b/frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/filter/ServerHeaderFilter.java new file mode 100644 index 00000000000..aa7c7fda4f9 --- /dev/null +++ b/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(); + } +} \ No newline at end of file diff --git a/frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/model/Fortune.java b/frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/model/Fortune.java similarity index 100% rename from frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/model/Fortune.java rename to frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/model/Fortune.java diff --git a/frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/model/World.java b/frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/model/World.java similarity index 100% rename from frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/model/World.java rename to frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/model/World.java diff --git a/frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/repository/pgclient/FortuneRepository.java b/frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/repository/FortuneRepository.java similarity index 94% rename from frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/repository/pgclient/FortuneRepository.java rename to frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/repository/FortuneRepository.java index 22cdd9bbdaf..4415583fa1d 100644 --- a/frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/repository/pgclient/FortuneRepository.java +++ b/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.List; diff --git a/frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/repository/pgclient/PgClientFactory.java b/frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/repository/PgClientFactory.java similarity index 96% rename from frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/repository/pgclient/PgClientFactory.java rename to frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/repository/PgClientFactory.java index b3c0fdf3eee..ef99489cb26 100644 --- a/frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/repository/pgclient/PgClientFactory.java +++ b/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.Pattern; diff --git a/frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/repository/pgclient/PgClients.java b/frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/repository/PgClients.java similarity index 94% rename from frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/repository/pgclient/PgClients.java rename to frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/repository/PgClients.java index 8f48963c965..871e9b75a6e 100644 --- a/frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/repository/pgclient/PgClients.java +++ b/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.sqlclient.SqlClient; diff --git a/frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/repository/pgclient/WorldRepository.java b/frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/repository/WorldRepository.java similarity index 95% rename from frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/repository/pgclient/WorldRepository.java rename to frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/repository/WorldRepository.java index d3b94cc21c3..2d9c71d1259 100644 --- a/frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/repository/pgclient/WorldRepository.java +++ b/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.Arrays; diff --git a/frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/resource/pgclient/BaseResource.java b/frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/resource/BaseResource.java similarity index 91% rename from frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/resource/pgclient/BaseResource.java rename to frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/resource/BaseResource.java index 3dc9cad2eb2..22e9965f777 100644 --- a/frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/resource/pgclient/BaseResource.java +++ b/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.json.Json; diff --git a/frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/resource/pgclient/DbResource.java b/frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/resource/DbResource.java similarity index 90% rename from frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/resource/pgclient/DbResource.java rename to frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/resource/DbResource.java index 941251499fa..6333ea49331 100644 --- a/frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/resource/pgclient/DbResource.java +++ b/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.concurrent.ThreadLocalRandom; @@ -7,7 +7,7 @@ import javax.inject.Inject; 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.smallrye.mutiny.Uni; import io.smallrye.mutiny.groups.UniAndGroupIterable; @@ -35,7 +35,7 @@ public void queries(RoutingContext rc) { return randomWorld().map(w -> ret[i] = w); }); - ((UniAndGroupIterable)Uni.combine().all().unis(worlds)) + Uni.combine().all().unis(worlds) .combinedWith(v -> Arrays.asList(ret)) .subscribe().with(list -> sendJson(rc, list), t -> handleFail(rc, t)); @@ -54,7 +54,7 @@ public void updates(RoutingContext rc) { }); }); - ((UniAndGroupIterable)Uni.combine().all().unis(worlds)) + Uni.combine().all().unis(worlds) .combinedWith(v -> null) .flatMap(v -> worldRepository.update(ret)) .map(v -> Arrays.asList(ret)) diff --git a/frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/resource/FortuneResource.java b/frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/resource/FortuneResource.java new file mode 100644 index 00000000000..acaf98b5487 --- /dev/null +++ b/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 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)); + } +} diff --git a/frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/resource/pgclient/JsonResource.java b/frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/resource/JsonResource.java similarity index 88% rename from frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/resource/pgclient/JsonResource.java rename to frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/resource/JsonResource.java index 2495db317ec..f6eb41e21e6 100644 --- a/frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/resource/pgclient/JsonResource.java +++ b/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; diff --git a/frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/resource/pgclient/Message.java b/frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/resource/Message.java similarity index 79% rename from frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/resource/pgclient/Message.java rename to frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/resource/Message.java index 64e63d0f018..73f0ffefb8a 100644 --- a/frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/resource/pgclient/Message.java +++ b/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 { private final String message; diff --git a/frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/resource/PlaintextResource.java b/frameworks/Java/quarkus/reactive-routes-pgclient/src/main/java/io/quarkus/benchmark/resource/PlaintextResource.java new file mode 100644 index 00000000000..3e6291c98f6 --- /dev/null +++ b/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); + } +} diff --git a/frameworks/Java/quarkus/pgclient/src/main/resources/application.properties b/frameworks/Java/quarkus/reactive-routes-pgclient/src/main/resources/application.properties similarity index 89% rename from frameworks/Java/quarkus/pgclient/src/main/resources/application.properties rename to frameworks/Java/quarkus/reactive-routes-pgclient/src/main/resources/application.properties index 727eacaa47f..4d99cfbc4ec 100644 --- a/frameworks/Java/quarkus/pgclient/src/main/resources/application.properties +++ b/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.username=benchmarkdbuser quarkus.datasource.password=benchmarkdbpass -quarkus.datasource.max-size=64 +quarkus.datasource.reactive.max-size=64 quarkus.log.console.enable=true quarkus.log.console.level=INFO quarkus.log.file.enable=false diff --git a/frameworks/Java/quarkus/reactive-routes-pgclient/src/main/resources/fortunes.mustache b/frameworks/Java/quarkus/reactive-routes-pgclient/src/main/resources/fortunes.mustache new file mode 100644 index 00000000000..f9664a72eee --- /dev/null +++ b/frameworks/Java/quarkus/reactive-routes-pgclient/src/main/resources/fortunes.mustache @@ -0,0 +1,20 @@ + + + + Fortunes + + + + + + + + {{#fortunes}} + + + + + {{/fortunes}} +
idmessage
{{id}}{{message}}
+ + diff --git a/frameworks/Java/quarkus/reactive-routes-pgclient/start-app.sh b/frameworks/Java/quarkus/reactive-routes-pgclient/start-app.sh new file mode 100755 index 00000000000..01b3e22ea2c --- /dev/null +++ b/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 + diff --git a/frameworks/Java/quarkus/hibernate/README.md b/frameworks/Java/quarkus/resteasy-hibernate/README.md similarity index 100% rename from frameworks/Java/quarkus/hibernate/README.md rename to frameworks/Java/quarkus/resteasy-hibernate/README.md diff --git a/frameworks/Java/quarkus/hibernate/pom.xml b/frameworks/Java/quarkus/resteasy-hibernate/pom.xml similarity index 56% rename from frameworks/Java/quarkus/hibernate/pom.xml rename to frameworks/Java/quarkus/resteasy-hibernate/pom.xml index be7cb2ae90c..d1dbf82f15b 100644 --- a/frameworks/Java/quarkus/hibernate/pom.xml +++ b/frameworks/Java/quarkus/resteasy-hibernate/pom.xml @@ -10,16 +10,28 @@ io.quarkus.benchmark - hibernate + resteasy-hibernate - io.quarkus.benchmark - base + io.quarkus + quarkus-hibernate-orm io.quarkus - quarkus-hibernate-orm + quarkus-scheduler + + + io.quarkus + quarkus-resteasy + + + io.quarkus + quarkus-resteasy-jackson + + + io.quarkus + quarkus-jdbc-postgresql com.github.spullara.mustache.java diff --git a/frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/cdi/HibernateOrmNativeComponents.java b/frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/cdi/HibernateOrmNativeComponents.java similarity index 85% rename from frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/cdi/HibernateOrmNativeComponents.java rename to frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/cdi/HibernateOrmNativeComponents.java index c8e4d643e2d..322517a3d40 100644 --- a/frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/cdi/HibernateOrmNativeComponents.java +++ b/frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/cdi/HibernateOrmNativeComponents.java @@ -1,6 +1,7 @@ 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; @@ -13,6 +14,8 @@ public class HibernateOrmNativeComponents { @PersistenceUnit EntityManagerFactory entityManagerFactory; + @Singleton + @Typed(SessionFactory.class) @Produces SessionFactory extractSessionFactory() { return entityManagerFactory.unwrap( SessionFactory.class ); diff --git a/frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/filter/ServerHeaderFilter.java b/frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/filter/ServerHeaderFilter.java similarity index 100% rename from frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/filter/ServerHeaderFilter.java rename to frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/filter/ServerHeaderFilter.java diff --git a/frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/model/Fortune.java b/frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/model/Fortune.java new file mode 100644 index 00000000000..5228080b02b --- /dev/null +++ b/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); + } +} \ No newline at end of file diff --git a/frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/model/World.java b/frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/model/World.java new file mode 100644 index 00000000000..a9a2acc4a82 --- /dev/null +++ b/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; + } + +} \ No newline at end of file diff --git a/frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/repository/hibernate/FortuneRepository.java b/frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/repository/FortuneRepository.java similarity index 82% rename from frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/repository/hibernate/FortuneRepository.java rename to frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/repository/FortuneRepository.java index eb0b02151f9..9b845ee39e9 100644 --- a/frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/repository/hibernate/FortuneRepository.java +++ b/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.Singleton; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; 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 { @Inject diff --git a/frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/repository/hibernate/WorldRepository.java b/frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/repository/WorldRepository.java similarity index 94% rename from frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/repository/hibernate/WorldRepository.java rename to frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/repository/WorldRepository.java index 271517cbb93..ee05796d892 100644 --- a/frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/repository/hibernate/WorldRepository.java +++ b/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.Collection; import java.util.Set; import java.util.concurrent.ThreadLocalRandom; -import java.util.stream.Collectors; + import javax.inject.Inject; import javax.inject.Singleton; import javax.transaction.Transactional; -import io.quarkus.benchmark.model.hibernate.World; 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 { @@ -46,6 +47,7 @@ public World findSingleAndStateless(int id) { } } + @Transactional public void updateAll(Collection worlds) { try (Session s = sf.openSession()) { s.setJdbcBatchSize(worlds.size()); diff --git a/frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/resource/hibernate/DbResource.java b/frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/resource/DbResource.java similarity index 96% rename from frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/resource/hibernate/DbResource.java rename to frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/resource/DbResource.java index e4b78337582..08ec68484cb 100644 --- a/frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/resource/hibernate/DbResource.java +++ b/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.HashSet; import java.util.Set; import java.util.concurrent.ThreadLocalRandom; + import javax.inject.Inject; import javax.inject.Singleton; import javax.ws.rs.Consumes; @@ -16,6 +14,9 @@ import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; +import io.quarkus.benchmark.model.World; +import io.quarkus.benchmark.repository.WorldRepository; + @Singleton @Path("/") diff --git a/frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/resource/hibernate/FortuneResource.java b/frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/resource/FortuneResource.java similarity index 83% rename from frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/resource/hibernate/FortuneResource.java rename to frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/resource/FortuneResource.java index c09de8b075e..fe71803f631 100644 --- a/frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/resource/hibernate/FortuneResource.java +++ b/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.util.ArrayList; @@ -6,8 +6,8 @@ import java.util.Comparator; import java.util.List; -import javax.enterprise.context.ApplicationScoped; import javax.inject.Inject; +import javax.inject.Singleton; import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.Path; @@ -17,12 +17,13 @@ import com.github.mustachejava.DefaultMustacheFactory; import com.github.mustachejava.Mustache; 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("/") -@Produces(MediaType.TEXT_HTML) +@Produces(MediaType.TEXT_HTML+"; charset=UTF-8") @Consumes(MediaType.APPLICATION_JSON) public class FortuneResource { diff --git a/frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/resource/JsonResource.java b/frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/resource/JsonResource.java similarity index 60% rename from frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/resource/JsonResource.java rename to frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/resource/JsonResource.java index 130a9e49451..c8bbb155545 100644 --- a/frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/resource/JsonResource.java +++ b/frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/resource/JsonResource.java @@ -4,18 +4,15 @@ import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; -import java.util.Collections; -import java.util.Map; @Path("/json") public class JsonResource { - private static final String MESSAGE = "message"; private static final String HELLO = "Hello, World!"; @GET @Produces(MediaType.APPLICATION_JSON) - public Map json() { - return Collections.singletonMap( MESSAGE, HELLO ); + public Message json() { + return new Message(HELLO); } } diff --git a/frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/resource/Message.java b/frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/resource/Message.java new file mode 100644 index 00000000000..73f0ffefb8a --- /dev/null +++ b/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; + } +} diff --git a/frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/resource/PlaintextResource.java b/frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/resource/PlaintextResource.java similarity index 100% rename from frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/resource/PlaintextResource.java rename to frameworks/Java/quarkus/resteasy-hibernate/src/main/java/io/quarkus/benchmark/resource/PlaintextResource.java diff --git a/frameworks/Java/quarkus/hibernate/src/main/resources/application.properties b/frameworks/Java/quarkus/resteasy-hibernate/src/main/resources/application.properties similarity index 53% rename from frameworks/Java/quarkus/hibernate/src/main/resources/application.properties rename to frameworks/Java/quarkus/resteasy-hibernate/src/main/resources/application.properties index bd41981e1c5..756e8f174d3 100644 --- a/frameworks/Java/quarkus/hibernate/src/main/resources/application.properties +++ b/frameworks/Java/quarkus/resteasy-hibernate/src/main/resources/application.properties @@ -1,15 +1,16 @@ #Test preferQueryMode ? sendBufferSize ? receiveBufferSize ? #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.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.level=INFO diff --git a/frameworks/Java/quarkus/resteasy-hibernate/src/main/resources/fortunes.mustache b/frameworks/Java/quarkus/resteasy-hibernate/src/main/resources/fortunes.mustache new file mode 100644 index 00000000000..f9664a72eee --- /dev/null +++ b/frameworks/Java/quarkus/resteasy-hibernate/src/main/resources/fortunes.mustache @@ -0,0 +1,20 @@ + + + + Fortunes + + + + + + + + {{#fortunes}} + + + + + {{/fortunes}} +
idmessage
{{id}}{{message}}
+ + diff --git a/frameworks/Java/quarkus/hibernate/src/main/resources/import.sql b/frameworks/Java/quarkus/resteasy-hibernate/src/main/resources/import.sql similarity index 100% rename from frameworks/Java/quarkus/hibernate/src/main/resources/import.sql rename to frameworks/Java/quarkus/resteasy-hibernate/src/main/resources/import.sql diff --git a/frameworks/Java/quarkus/hibernate/start-app.sh b/frameworks/Java/quarkus/resteasy-hibernate/start-app.sh similarity index 100% rename from frameworks/Java/quarkus/hibernate/start-app.sh rename to frameworks/Java/quarkus/resteasy-hibernate/start-app.sh diff --git a/frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/pom.xml b/frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/pom.xml new file mode 100644 index 00000000000..77a1e4ba881 --- /dev/null +++ b/frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/pom.xml @@ -0,0 +1,51 @@ + + + 4.0.0 + + + io.quarkus + benchmark + 1.0-SNAPSHOT + ../ + + + io.quarkus.benchmark + resteasy-reactive-hibernate-reactive + + + + io.quarkus + quarkus-scheduler + + + io.quarkus + quarkus-reactive-pg-client + + + io.quarkus + quarkus-hibernate-reactive + + + io.quarkus + quarkus-resteasy-reactive + + + io.quarkus + quarkus-resteasy-reactive-jackson + + + io.vertx + vertx-web-templ-rocker + + + io.netty + netty-transport-native-epoll + linux-x86_64 + + + com.github.spullara.mustache.java + compiler + 0.9.6 + + + diff --git a/frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/filter/ServerHeaderFilter.java b/frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/filter/ServerHeaderFilter.java new file mode 100644 index 00000000000..d19fe291e53 --- /dev/null +++ b/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); + } +} \ No newline at end of file diff --git a/frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/model/Fortune.java b/frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/model/Fortune.java new file mode 100644 index 00000000000..5228080b02b --- /dev/null +++ b/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); + } +} \ No newline at end of file diff --git a/frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/model/World.java b/frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/model/World.java new file mode 100644 index 00000000000..a9a2acc4a82 --- /dev/null +++ b/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; + } + +} \ No newline at end of file diff --git a/frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/repository/BaseRepository.java b/frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/repository/BaseRepository.java new file mode 100644 index 00000000000..8cc1e2e9a01 --- /dev/null +++ b/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 Uni inSession(Function> work){ + return sf.withSession(session -> work.apply(session)); + } + +} diff --git a/frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/repository/FortuneRepository.java b/frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/repository/FortuneRepository.java new file mode 100644 index 00000000000..a34254a0825 --- /dev/null +++ b/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> findAll() { + return inSession(s -> { + CriteriaBuilder criteriaBuilder = sf.getCriteriaBuilder(); + CriteriaQuery fortuneQuery = criteriaBuilder.createQuery(Fortune.class); + Root from = fortuneQuery.from(Fortune.class); + fortuneQuery.select(from); + return s.createQuery(fortuneQuery).getResultList(); + }); + } +} diff --git a/frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/repository/WorldRepository.java b/frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/repository/WorldRepository.java new file mode 100644 index 00000000000..bc236b0e4ca --- /dev/null +++ b/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 createData() { + return inSession(s -> { + final ThreadLocalRandom random = ThreadLocalRandom.current(); + int MAX = 10000; + Uni[] unis = new Uni[MAX]; + for (int i=0; i null); + } + return Uni.combine().all().unis(unis).combinedWith(l -> null) + .flatMap(v -> s.flush()) + .map(v -> null); + }); + } + + public Uni find(int id) { + return inSession(session -> singleFind(session, id)); + } + + public Uni> update(Mutiny.Session s, Collection worlds) { + return s.flush() + .map(v -> worlds); + } + + public Uni> find(Session s, Set ids) { + //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(singleFind(s, id)); + } + return Uni.combine().all().unis(l).combinedWith(list -> (List)list); + } + + private static Uni singleFind(final Mutiny.Session ss, final Integer id) { + return ss.find(World.class, id); + } + +} diff --git a/frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/resource/DbResource.java b/frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/resource/DbResource.java new file mode 100644 index 00000000000..4f5316fd95f --- /dev/null +++ b/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 db() { + return randomWorld(); + } + + @GET + @Path("queries") + public Uni> queries(@QueryParam("queries") String queries) { + return worldRepository.inSession(session -> randomWorldForRead(session, parseQueryCount(queries))); + } + + private Uni> randomWorldForRead(Mutiny.Session session, int count) { + Set 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> 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 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)); + } +} \ No newline at end of file diff --git a/frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/resource/FortuneResource.java b/frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/resource/FortuneResource.java new file mode 100644 index 00000000000..4b23849cb2e --- /dev/null +++ b/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 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 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(); + }); + } +} diff --git a/frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/resource/JsonResource.java b/frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/resource/JsonResource.java new file mode 100644 index 00000000000..c1cd3a3eb14 --- /dev/null +++ b/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); + } +} + diff --git a/frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/resource/Message.java b/frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/resource/Message.java new file mode 100644 index 00000000000..73f0ffefb8a --- /dev/null +++ b/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; + } +} diff --git a/frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/resource/PlaintextResource.java b/frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/java/io/quarkus/benchmark/resource/PlaintextResource.java new file mode 100644 index 00000000000..58094ad21ef --- /dev/null +++ b/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; + } +} diff --git a/frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/resources/application.properties b/frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/resources/application.properties new file mode 100644 index 00000000000..18e5ae2367b --- /dev/null +++ b/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 \ No newline at end of file diff --git a/frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/resources/fortunes.mustache b/frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/resources/fortunes.mustache new file mode 100644 index 00000000000..f9664a72eee --- /dev/null +++ b/frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/src/main/resources/fortunes.mustache @@ -0,0 +1,20 @@ + + + + Fortunes + + + + + + + + {{#fortunes}} + + + + + {{/fortunes}} +
idmessage
{{id}}{{message}}
+ + diff --git a/frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/start-app.sh b/frameworks/Java/quarkus/resteasy-reactive-hibernate-reactive/start-app.sh new file mode 100755 index 00000000000..01b3e22ea2c --- /dev/null +++ b/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 + diff --git a/frameworks/Java/quarkus/resteasy-reactive-hibernate/README.md b/frameworks/Java/quarkus/resteasy-reactive-hibernate/README.md new file mode 100644 index 00000000000..7cbe9419a38 --- /dev/null +++ b/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 \ No newline at end of file diff --git a/frameworks/Java/quarkus/resteasy-reactive-hibernate/pom.xml b/frameworks/Java/quarkus/resteasy-reactive-hibernate/pom.xml new file mode 100644 index 00000000000..2336a8ee4c5 --- /dev/null +++ b/frameworks/Java/quarkus/resteasy-reactive-hibernate/pom.xml @@ -0,0 +1,44 @@ + + + 4.0.0 + + + io.quarkus + benchmark + 1.0-SNAPSHOT + ../ + + + io.quarkus.benchmark + resteasy-reactive-hibernate + + + + io.quarkus + quarkus-hibernate-orm + + + io.quarkus + quarkus-scheduler + + + io.quarkus + quarkus-resteasy-reactive + + + io.quarkus + quarkus-resteasy-reactive-jackson + + + io.quarkus + quarkus-jdbc-postgresql + + + com.github.spullara.mustache.java + compiler + 0.9.6 + + + + + diff --git a/frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/cdi/HibernateOrmNativeComponents.java b/frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/cdi/HibernateOrmNativeComponents.java new file mode 100644 index 00000000000..322517a3d40 --- /dev/null +++ b/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 ); + } + +} diff --git a/frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/filter/ServerHeaderFilter.java b/frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/filter/ServerHeaderFilter.java new file mode 100644 index 00000000000..7043dd284e2 --- /dev/null +++ b/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 headers = responseContext.getHeaders(); + headers.add( "Server", "Quarkus"); + headers.add( "Date", date); + } +} \ No newline at end of file diff --git a/frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/model/Fortune.java b/frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/model/Fortune.java new file mode 100644 index 00000000000..5228080b02b --- /dev/null +++ b/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); + } +} \ No newline at end of file diff --git a/frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/model/World.java b/frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/model/World.java new file mode 100644 index 00000000000..a9a2acc4a82 --- /dev/null +++ b/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; + } + +} \ No newline at end of file diff --git a/frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/repository/FortuneRepository.java b/frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/repository/FortuneRepository.java new file mode 100644 index 00000000000..9b845ee39e9 --- /dev/null +++ b/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 findAllStateless() { + try (StatelessSession s = sf.openStatelessSession()) { + CriteriaBuilder criteriaBuilder = sf.getCriteriaBuilder(); + CriteriaQuery fortuneQuery = criteriaBuilder.createQuery(Fortune.class); + Root from = fortuneQuery.from(Fortune.class); + fortuneQuery.select(from); + return s.createQuery(fortuneQuery).getResultList(); + } + } +} diff --git a/frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/repository/WorldRepository.java b/frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/repository/WorldRepository.java new file mode 100644 index 00000000000..ee05796d892 --- /dev/null +++ b/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 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 findReadonly(Set 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); + } + +} diff --git a/frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/resource/DbResource.java b/frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/resource/DbResource.java new file mode 100644 index 00000000000..0354cc3aadd --- /dev/null +++ b/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 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 randomWorldForRead(int count) { + Set 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)); + } +} diff --git a/frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/resource/FortuneResource.java b/frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/resource/FortuneResource.java new file mode 100644 index 00000000000..2724a301a9d --- /dev/null +++ b/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 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 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(); + } +} diff --git a/frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/resource/JsonResource.java b/frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/resource/JsonResource.java new file mode 100644 index 00000000000..c8bbb155545 --- /dev/null +++ b/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); + } +} + diff --git a/frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/resource/Message.java b/frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/resource/Message.java new file mode 100644 index 00000000000..73f0ffefb8a --- /dev/null +++ b/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; + } +} diff --git a/frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/resource/PlaintextResource.java b/frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/java/io/quarkus/benchmark/resource/PlaintextResource.java new file mode 100644 index 00000000000..8acadbfeb7e --- /dev/null +++ b/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; + } +} diff --git a/frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/resources/application.properties b/frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/resources/application.properties new file mode 100644 index 00000000000..756e8f174d3 --- /dev/null +++ b/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 + + + diff --git a/frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/resources/fortunes.mustache b/frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/resources/fortunes.mustache new file mode 100644 index 00000000000..f9664a72eee --- /dev/null +++ b/frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/resources/fortunes.mustache @@ -0,0 +1,20 @@ + + + + Fortunes + + + + + + + + {{#fortunes}} + + + + + {{/fortunes}} +
idmessage
{{id}}{{message}}
+ + diff --git a/frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/resources/import.sql b/frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/resources/import.sql new file mode 100644 index 00000000000..f76881b4287 --- /dev/null +++ b/frameworks/Java/quarkus/resteasy-reactive-hibernate/src/main/resources/import.sql @@ -0,0 +1 @@ +INSERT INTO Fortune(id, message) VALUES (1, 'Test value One'); \ No newline at end of file diff --git a/frameworks/Java/quarkus/resteasy-reactive-hibernate/start-app.sh b/frameworks/Java/quarkus/resteasy-reactive-hibernate/start-app.sh new file mode 100755 index 00000000000..f224e71fb26 --- /dev/null +++ b/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 diff --git a/frameworks/Java/quarkus/resteasy-reactive-pgclient/.factorypath b/frameworks/Java/quarkus/resteasy-reactive-pgclient/.factorypath new file mode 100644 index 00000000000..268ec46be2b --- /dev/null +++ b/frameworks/Java/quarkus/resteasy-reactive-pgclient/.factorypath @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frameworks/Java/quarkus/resteasy-reactive-pgclient/pom.xml b/frameworks/Java/quarkus/resteasy-reactive-pgclient/pom.xml new file mode 100644 index 00000000000..eca074a80a1 --- /dev/null +++ b/frameworks/Java/quarkus/resteasy-reactive-pgclient/pom.xml @@ -0,0 +1,47 @@ + + + 4.0.0 + + + io.quarkus + benchmark + 1.0-SNAPSHOT + ../ + + + io.quarkus.benchmark + resteasy-reactive-pgclient + + + + io.quarkus + quarkus-scheduler + + + io.quarkus + quarkus-reactive-pg-client + + + io.quarkus + quarkus-resteasy-reactive + + + io.quarkus + quarkus-resteasy-reactive-jackson + + + io.vertx + vertx-web-templ-rocker + + + io.netty + netty-transport-native-epoll + linux-x86_64 + + + com.github.spullara.mustache.java + compiler + 0.9.6 + + + diff --git a/frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/java/io/quarkus/benchmark/filter/ServerHeaderFilter.java b/frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/java/io/quarkus/benchmark/filter/ServerHeaderFilter.java new file mode 100644 index 00000000000..d19fe291e53 --- /dev/null +++ b/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); + } +} \ No newline at end of file diff --git a/frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/java/io/quarkus/benchmark/model/Fortune.java b/frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/java/io/quarkus/benchmark/model/Fortune.java new file mode 100644 index 00000000000..0e32970c9db --- /dev/null +++ b/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); + } +} \ No newline at end of file diff --git a/frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/java/io/quarkus/benchmark/model/World.java b/frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/java/io/quarkus/benchmark/model/World.java new file mode 100644 index 00000000000..0d5205ae361 --- /dev/null +++ b/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{ + + 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); + } +} \ No newline at end of file diff --git a/frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/java/io/quarkus/benchmark/repository/FortuneRepository.java b/frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/java/io/quarkus/benchmark/repository/FortuneRepository.java new file mode 100644 index 00000000000..4415583fa1d --- /dev/null +++ b/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> findAll() { + return clients.getClient().preparedQuery("SELECT * FROM Fortune" ) + .execute() + .map(rowset -> { + List ret = new ArrayList<>(rowset.size()+1); + for(Row r : rowset) { + ret.add(new Fortune(r.getInteger("id"), r.getString("message"))); + } + return ret; + }); + } +} diff --git a/frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/java/io/quarkus/benchmark/repository/PgClientFactory.java b/frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/java/io/quarkus/benchmark/repository/PgClientFactory.java new file mode 100644 index 00000000000..ef99489cb26 --- /dev/null +++ b/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); + } +} \ No newline at end of file diff --git a/frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/java/io/quarkus/benchmark/repository/PgClients.java b/frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/java/io/quarkus/benchmark/repository/PgClients.java new file mode 100644 index 00000000000..871e9b75a6e --- /dev/null +++ b/frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/java/io/quarkus/benchmark/repository/PgClients.java @@ -0,0 +1,38 @@ +package io.quarkus.benchmark.repository; + +import io.vertx.mutiny.pgclient.PgPool; +import io.vertx.mutiny.sqlclient.SqlClient; + +class PgClients { + private static final int POOL_SIZE = 4; + + private ThreadLocal sqlClient = new ThreadLocal<>(); + private ThreadLocal pool = new ThreadLocal<>(); + private PgClientFactory pgClientFactory; + + // for ArC + public PgClients() { + } + + public PgClients(PgClientFactory pgClientFactory) { + this.pgClientFactory = pgClientFactory; + } + + SqlClient getClient() { + SqlClient ret = sqlClient.get(); + if(ret == null) { + ret = pgClientFactory.sqlClient(1); + sqlClient.set(ret); + } + return ret; + } + + synchronized PgPool getPool() { + PgPool ret = pool.get(); + if(ret == null) { + ret = pgClientFactory.sqlClient(POOL_SIZE); + pool.set(ret); + } + return ret; + } +} \ No newline at end of file diff --git a/frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/java/io/quarkus/benchmark/repository/WorldRepository.java b/frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/java/io/quarkus/benchmark/repository/WorldRepository.java new file mode 100644 index 00000000000..2d9c71d1259 --- /dev/null +++ b/frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/java/io/quarkus/benchmark/repository/WorldRepository.java @@ -0,0 +1,40 @@ +package io.quarkus.benchmark.repository; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.enterprise.context.ApplicationScoped; +import javax.inject.Inject; + +import io.quarkus.benchmark.model.World; +import io.smallrye.mutiny.Uni; +import io.vertx.mutiny.sqlclient.Row; +import io.vertx.mutiny.sqlclient.Tuple; + +@ApplicationScoped +public class WorldRepository { + + @Inject + PgClients clients; + + public Uni find(int id) { + return clients.getClient().preparedQuery("SELECT id, randomNumber FROM World WHERE id = $1") + .execute(Tuple.of(id)) + .map(rowset -> { + Row row = rowset.iterator().next(); + return new World(row.getInteger(0), row.getInteger(1)); + }); + } + + public Uni update(World[] worlds) { + Arrays.sort(worlds); + List args = new ArrayList<>(worlds.length); + for (World world : worlds) { + args.add(Tuple.of(world.getId(), world.getRandomNumber())); + } + return clients.getPool().preparedQuery("UPDATE World SET randomNumber = $2 WHERE id = $1") + .executeBatch(args) + .map(v -> null); + } +} diff --git a/frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/java/io/quarkus/benchmark/resource/DbResource.java b/frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/java/io/quarkus/benchmark/resource/DbResource.java new file mode 100644 index 00000000000..fe87893d095 --- /dev/null +++ b/frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/java/io/quarkus/benchmark/resource/DbResource.java @@ -0,0 +1,83 @@ +package io.quarkus.benchmark.resource; + +import java.util.Arrays; +import java.util.List; +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 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 db() { + return randomWorld(); + } + + @GET + @Path("queries") + public Uni> queries(@QueryParam("queries") String queries) { + var worlds = new Uni[parseQueryCount(queries)]; + var ret = new World[worlds.length]; + Arrays.setAll(worlds, i -> { + return randomWorld().map(w -> ret[i] = w); + }); + + return Uni.combine().all().unis(worlds) + .combinedWith(v -> Arrays.asList(ret)); + } + + @GET + @Path("updates") + public Uni> updates(@QueryParam("queries") String queries) { + var worlds = new Uni[parseQueryCount(queries)]; + var ret = new World[worlds.length]; + Arrays.setAll(worlds, i -> { + return randomWorld().map(w -> { + w.setRandomNumber(randomWorldNumber()); + ret[i] = w; + return w; + }); + }); + + return Uni.combine().all().unis(worlds) + .combinedWith(v -> null) + .flatMap(v -> worldRepository.update(ret)) + .map(v -> Arrays.asList(ret)); + } + + private Uni randomWorld() { + return worldRepository.find(randomWorldNumber()); + } + + private int randomWorldNumber() { + return 1 + ThreadLocalRandom.current().nextInt(10000); + } + + 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)); + } +} \ No newline at end of file diff --git a/frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/java/io/quarkus/benchmark/resource/FortuneResource.java b/frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/java/io/quarkus/benchmark/resource/FortuneResource.java new file mode 100644 index 00000000000..4b23849cb2e --- /dev/null +++ b/frameworks/Java/quarkus/resteasy-reactive-pgclient/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 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 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(); + }); + } +} diff --git a/frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/java/io/quarkus/benchmark/resource/JsonResource.java b/frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/java/io/quarkus/benchmark/resource/JsonResource.java new file mode 100644 index 00000000000..c1cd3a3eb14 --- /dev/null +++ b/frameworks/Java/quarkus/resteasy-reactive-pgclient/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); + } +} + diff --git a/frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/java/io/quarkus/benchmark/resource/Message.java b/frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/java/io/quarkus/benchmark/resource/Message.java new file mode 100644 index 00000000000..73f0ffefb8a --- /dev/null +++ b/frameworks/Java/quarkus/resteasy-reactive-pgclient/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; + } +} diff --git a/frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/java/io/quarkus/benchmark/resource/PlaintextResource.java b/frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/java/io/quarkus/benchmark/resource/PlaintextResource.java new file mode 100644 index 00000000000..58094ad21ef --- /dev/null +++ b/frameworks/Java/quarkus/resteasy-reactive-pgclient/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; + } +} diff --git a/frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/resources/application.properties b/frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/resources/application.properties new file mode 100644 index 00000000000..0a1d6083f99 --- /dev/null +++ b/frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/resources/application.properties @@ -0,0 +1,10 @@ +quarkus.datasource.url=vertx-reactive:postgresql://tfb-database:5432/hello_world +%dev.quarkus.datasource.url=vertx-reactive:postgresql://localhost:5432/hello_world +quarkus.datasource.username=benchmarkdbuser +quarkus.datasource.password=benchmarkdbpass +quarkus.datasource.reactive.max-size=64 +quarkus.log.console.enable=true +quarkus.log.console.level=INFO +quarkus.log.file.enable=false +quarkus.log.level=INFO +quarkus.vertx.prefer-native-transport=true \ No newline at end of file diff --git a/frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/resources/fortunes.mustache b/frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/resources/fortunes.mustache new file mode 100644 index 00000000000..f9664a72eee --- /dev/null +++ b/frameworks/Java/quarkus/resteasy-reactive-pgclient/src/main/resources/fortunes.mustache @@ -0,0 +1,20 @@ + + + + Fortunes + + + + + + + + {{#fortunes}} + + + + + {{/fortunes}} +
idmessage
{{id}}{{message}}
+ + diff --git a/frameworks/Java/quarkus/resteasy-reactive-pgclient/start-app.sh b/frameworks/Java/quarkus/resteasy-reactive-pgclient/start-app.sh new file mode 100755 index 00000000000..01b3e22ea2c --- /dev/null +++ b/frameworks/Java/quarkus/resteasy-reactive-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 +