Browse Source

Update all play2-java benchmark projects (#3061)

Matthias Kurz 7 years ago
parent
commit
4401dfbfc1
46 changed files with 362 additions and 599 deletions
  1. 6 6
      frameworks/Java/play2-java/benchmark_config.json
  2. 0 1
      frameworks/Java/play2-java/play2-java-ebean-hikaricp/.gitignore
  3. 1 13
      frameworks/Java/play2-java/play2-java-ebean-hikaricp/README.md
  4. 34 53
      frameworks/Java/play2-java/play2-java-ebean-hikaricp/app/controllers/Application.java
  5. 0 37
      frameworks/Java/play2-java/play2-java-ebean-hikaricp/app/inject/AppModule.java
  6. 9 6
      frameworks/Java/play2-java/play2-java-ebean-hikaricp/app/models/Fortune.java
  7. 25 8
      frameworks/Java/play2-java/play2-java-ebean-hikaricp/app/models/World.java
  8. 15 0
      frameworks/Java/play2-java/play2-java-ebean-hikaricp/app/utils/DatabaseExecutionContext.java
  9. 0 21
      frameworks/Java/play2-java/play2-java-ebean-hikaricp/app/utils/Headers.java
  10. 0 8
      frameworks/Java/play2-java/play2-java-ebean-hikaricp/app/utils/Predicate.java
  11. 0 26
      frameworks/Java/play2-java/play2-java-ebean-hikaricp/app/utils/Predicated.java
  12. 0 28
      frameworks/Java/play2-java/play2-java-ebean-hikaricp/app/utils/PredicatedAction.java
  13. 3 4
      frameworks/Java/play2-java/play2-java-ebean-hikaricp/build.sbt
  14. 55 48
      frameworks/Java/play2-java/play2-java-ebean-hikaricp/conf/application.conf
  15. 8 2
      frameworks/Java/play2-java/play2-java-ebean-hikaricp/conf/logback.xml
  16. 2 7
      frameworks/Java/play2-java/play2-java-ebean-hikaricp/conf/routes
  17. 1 1
      frameworks/Java/play2-java/play2-java-ebean-hikaricp/project/build.properties
  18. 3 2
      frameworks/Java/play2-java/play2-java-ebean-hikaricp/project/plugins.sbt
  19. 8 11
      frameworks/Java/play2-java/play2-java-ebean-hikaricp/source_code
  20. 1 14
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/README.md
  21. 38 72
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/controllers/Application.java
  22. 8 7
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/models/Fortune.java
  23. 19 7
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/models/World.java
  24. 15 0
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/utils/DatabaseExecutionContext.java
  25. 0 21
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/utils/Headers.java
  26. 0 8
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/utils/Predicate.java
  27. 0 26
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/utils/Predicated.java
  28. 0 23
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/utils/PredicatedAction.java
  29. 5 7
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/build.sbt
  30. 1 0
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/conf/META-INF/persistence.xml
  31. 55 58
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/conf/application.conf
  32. 9 3
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/conf/logback.xml
  33. 2 6
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/conf/routes
  34. 1 1
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/project/build.properties
  35. 1 1
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/project/plugins.sbt
  36. 8 11
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/source_code
  37. 1 1
      frameworks/Java/play2-java/play2-java/README.md
  38. 3 7
      frameworks/Java/play2-java/play2-java/app/controllers/Application.java
  39. 0 21
      frameworks/Java/play2-java/play2-java/app/utils/Headers.java
  40. 4 5
      frameworks/Java/play2-java/play2-java/build.sbt
  41. 5 4
      frameworks/Java/play2-java/play2-java/conf/application.conf
  42. 9 3
      frameworks/Java/play2-java/play2-java/conf/logback.xml
  43. 2 6
      frameworks/Java/play2-java/play2-java/conf/routes
  44. 1 1
      frameworks/Java/play2-java/play2-java/project/build.properties
  45. 1 1
      frameworks/Java/play2-java/play2-java/project/plugins.sbt
  46. 3 3
      frameworks/Java/play2-java/play2-java/source_code

+ 6 - 6
frameworks/Java/play2-java/benchmark_config.json

@@ -13,11 +13,11 @@
         "database": "None", 
         "approach": "Realistic", 
         "classification": "Fullstack", 
-        "platform": "Netty", 
+        "platform": "Akka", 
         "webserver": "None", 
         "database_os": "Linux", 
         "notes": "", 
-        "versus": "netty", 
+        "versus": "akka-http", 
         "port": "9000", 
         "json_url": "/json", 
         "plaintext_url": "/plaintext"
@@ -33,11 +33,11 @@
         "database": "MySQL", 
         "approach": "Realistic", 
         "classification": "Fullstack", 
-        "platform": "Netty", 
+        "platform": "Akka", 
         "webserver": "None", 
         "database_os": "Linux", 
         "notes": "", 
-        "versus": "netty", 
+        "versus": "akka-http", 
         "port": "9000", 
         "db_url": "/db", 
         "query_url": "/queries?queries=", 
@@ -55,11 +55,11 @@
         "database": "MySQL", 
         "approach": "Realistic", 
         "classification": "Fullstack", 
-        "platform": "Netty", 
+        "platform": "Akka", 
         "webserver": "None", 
         "database_os": "Linux", 
         "notes": "", 
-        "versus": "netty", 
+        "versus": "akka-http", 
         "port": "9000", 
         "db_url": "/db", 
         "query_url": "/queries?queries=", 

+ 0 - 1
frameworks/Java/play2-java/play2-java-ebean-hikaricp/.gitignore

@@ -27,4 +27,3 @@ test-result
 server.pid
 *.iml
 *.eml
-

+ 1 - 13
frameworks/Java/play2-java/play2-java-ebean-hikaricp/README.md

@@ -2,31 +2,19 @@
 
 This is the Play portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
 
-### JSON Encoding Test
-
-* [JSON test controller](app/controllers/Application.java)
-
 ### Data-Store/Database Mapping Test
 
 * [Database test controller](app/controllers/Application.java)
 * [Database World test model](app/models/World.java)
 * [Database Fortune test model](app/models/Fortune.java)
 
-### Plain Text Test
-
-* [Plain text test controller](app/controllers/Application.java)
-
 ## Infrastructure Software Versions
 The tests were run with:
 
 * Java 8
-* [Play 2.5.14](https://www.playframework.com/)
+* [Play 2.6.7](https://www.playframework.com/)
 
 ## Test URLs
-### JSON Encoding Test
-
-* http://localhost/json
-
 ### Data-Store/Database Mapping Test
 
 * http://localhost/db

+ 34 - 53
frameworks/Java/play2-java/play2-java-ebean-hikaricp/app/controllers/Application.java

@@ -1,60 +1,42 @@
 package controllers;
 
-import com.google.inject.name.Named;
-import models.Fortune;
-import models.World;
-import play.Play;
-import play.libs.F;
-import play.libs.Json;
-import play.mvc.Controller;
-import play.mvc.Result;
-import play.mvc.With;
-import scala.concurrent.ExecutionContext;
-import utils.Headers;
-import utils.Predicate;
-import utils.Predicated;
-
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Random;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionStage;
 import java.util.concurrent.ThreadLocalRandom;
-import java.util.concurrent.ThreadPoolExecutor;
+
 import javax.inject.Inject;
 
-@With(Headers.class)
-public class Application extends Controller {
+import models.Fortune;
+import models.World;
+import play.libs.Json;
+import play.mvc.Controller;
+import play.mvc.Result;
+import utils.DatabaseExecutionContext;
 
-    private static final int TEST_DATABASE_ROWS = 10000;
+public class Application extends Controller {
 
-    @Inject @Named("dbEc") private ExecutionContext dbEc;
+    private final DatabaseExecutionContext dbEc;
 
-    // If the thread-pool used by the database grows too large then our server
-    // is probably struggling, and we should start dropping requests. Set
-    // the max size of our queue something above the number of concurrent
-    // connections that we need to handle.
-    public static class IsDbAvailable implements Predicate {
-        @Inject @Named("dbTpe") private ThreadPoolExecutor tpe;
-        @Override
-        public boolean condition() {
-            return tpe.getQueue().size() <= 1024;
-        }
+    @Inject
+    public Application(final DatabaseExecutionContext dbEc) {
+        this.dbEc = dbEc;
     }
 
-    @Predicated(predicate = IsDbAvailable.class, failed = SERVICE_UNAVAILABLE)
-    public F.Promise<Result> db() {
-        return getRandomWorlds(1).map(worlds -> ok(Json.toJson(worlds.get(0))));
+    public CompletionStage<Result> db() {
+        return getRandomWorlds(1).thenApply(worlds -> ok(Json.toJson(worlds.get(0))));
     }
 
-    @Predicated(predicate = IsDbAvailable.class, failed = SERVICE_UNAVAILABLE)
-    public F.Promise<Result> queries(final String queryCountString) {
-        return getRandomWorlds(queryCount(queryCountString)).map(worlds -> ok(Json.toJson(worlds)));
+    public CompletionStage<Result> queries(final String queries) {
+        return getRandomWorlds(queryCount(queries)).thenApply(worlds -> ok(Json.toJson(worlds)));
     }
 
-    @Predicated(predicate = IsDbAvailable.class, failed = SERVICE_UNAVAILABLE)
-    public F.Promise<Result> fortunes() {
-        return F.Promise.promise(() -> {
-            List<Fortune> fortunes = Fortune.findAll();
+    public CompletionStage<Result> fortunes() {
+        return CompletableFuture.supplyAsync(() -> {
+            final List<Fortune> fortunes = Fortune.findAll();
             fortunes.add(new Fortune("Additional fortune added at request time."));
             Collections.sort(fortunes, (f1, f2) -> f1.message.compareTo(f2.message));
 
@@ -62,24 +44,23 @@ public class Application extends Controller {
         }, dbEc);
     }
 
-    @Predicated(predicate = IsDbAvailable.class, failed = SERVICE_UNAVAILABLE)
-    public F.Promise<Result> update(final String queryCountString) {
-        return getRandomWorlds(queryCount(queryCountString)).map(worlds -> {
-            Random random = ThreadLocalRandom.current();
-            for (World world : worlds) {
+    public CompletionStage<Result> update(final String queries) {
+        return getRandomWorlds(queryCount(queries)).thenApplyAsync(worlds -> {
+            final Random random = ThreadLocalRandom.current();
+            for (final World world : worlds) {
                 world.randomNumber = (long) (random.nextInt(10000) + 1);
             }
 
-            List<World> updatedWorlds = World.save(worlds);
+            final List<World> updatedWorlds = World.save(worlds);
             return ok(Json.toJson(updatedWorlds));
         }, dbEc);
     }
 
-    private int queryCount(String queryCountString) {
+    private int queryCount(final String queryCountString) {
         int queryCount;
         try {
             queryCount = Integer.parseInt(queryCountString, 10);
-        } catch (NumberFormatException e) {
+        } catch (final NumberFormatException e) {
             queryCount = 1;
         }
         if (queryCount < 1) {
@@ -91,13 +72,13 @@ public class Application extends Controller {
         return queryCount;
     }
 
-    private F.Promise<List<World>> getRandomWorlds(final int n) {
-        return F.Promise.promise(() -> {
-            Random random = ThreadLocalRandom.current();
-            List<World> worlds = new ArrayList<>(n);
+    private CompletionStage<List<World>> getRandomWorlds(final int n) {
+        return CompletableFuture.supplyAsync(() -> {
+            final Random random = ThreadLocalRandom.current();
+            final List<World> worlds = new ArrayList<>(n);
             for (int i = 0; i < n; ++i) {
-                long randomId = random.nextInt(TEST_DATABASE_ROWS) + 1;
-                World world = World.find(randomId);
+                long randomId = random.nextInt(10000) + 1;
+                final World world = World.find(randomId);
                 worlds.add(world);
             }
             return worlds;

+ 0 - 37
frameworks/Java/play2-java/play2-java-ebean-hikaricp/app/inject/AppModule.java

@@ -1,37 +0,0 @@
-package inject;
-
-import akka.dispatch.ExecutionContexts;
-import com.google.inject.AbstractModule;
-import com.google.inject.Provides;
-import com.google.inject.Singleton;
-import com.google.inject.name.Named;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-import play.Configuration;
-import play.core.NamedThreadFactory;
-import scala.concurrent.ExecutionContext;
-
-public class AppModule extends AbstractModule {
-
-  protected void configure() {
-  }
-
-  @Provides @Singleton @Named("dbTpe")
-  public ThreadPoolExecutor provideThreadPoolExecutor(Configuration configuration) {
-    int partitionCount = configuration.getInt("db.default.partitionCount");
-    int maxConnections = partitionCount * configuration.getInt("db.default.maxConnectionsPerPartition");
-    int minConnections = partitionCount * configuration.getInt("db.default.minConnectionsPerPartition");
-
-    return new ThreadPoolExecutor(minConnections, maxConnections,
-            0L, TimeUnit.MILLISECONDS,
-            new LinkedBlockingQueue<>(),
-            new NamedThreadFactory("dbEc"));
-  }
-
-  @Provides @Singleton @Named("dbEc")
-  public ExecutionContext provideExecutionContext(@Named("dbTpe") ThreadPoolExecutor tpe) {
-    return ExecutionContexts.fromExecutorService(tpe);
-  }
-
-}

+ 9 - 6
frameworks/Java/play2-java/play2-java-ebean-hikaricp/app/models/Fortune.java

@@ -1,15 +1,18 @@
 package models;
 
-import com.avaje.ebean.Ebean;
-import com.avaje.ebean.Model;
+import java.util.List;
 
 import javax.persistence.Entity;
 import javax.persistence.Id;
-import java.util.List;
+
+import io.ebean.Finder;
+import io.ebean.Model;
 
 @Entity
 public class Fortune extends Model {
 
+    private static final Finder<Long, Fortune> find = new Finder<>(Fortune.class);
+
     @Id
     public Long id = 0L;
 
@@ -18,11 +21,11 @@ public class Fortune extends Model {
     public Fortune() {
     }
 
-    public Fortune(String message) {
+    public Fortune(final String message) {
         this.message = message;
     }
 
     public static List<Fortune> findAll() {
-        return Ebean.find(Fortune.class).findList();
+        return find.all();
     }
-}
+}

+ 25 - 8
frameworks/Java/play2-java/play2-java-ebean-hikaricp/app/models/World.java

@@ -1,30 +1,47 @@
 package models;
 
-import com.avaje.ebean.Ebean;
-import com.avaje.ebean.Model;
+import java.util.List;
 
 import javax.persistence.Column;
 import javax.persistence.Entity;
 import javax.persistence.Id;
-import java.util.List;
+
+import io.ebean.Finder;
+import io.ebean.Model;
+import io.ebean.Transaction;
 
 @Entity
 public class World extends Model {
 
+    private static final Finder<Long, World> find = new Finder<>(World.class);
+
     @Id
     public Long id;
 
     @Column(name = "randomNumber")
     public Long randomNumber;
 
-    public static World find(Long id) {
-        return Ebean.find(World.class, id);
+    public static World find(final Long id) {
+        return find.byId(id);
     }
 
     public static List<World> save(final List<World> worlds) {
-        worlds.forEach(Ebean::update);
+        final int batchSize = 25;
+        final int batches = ((worlds.size() / batchSize) + 1);
+        for ( int i = 0 ; i < batches ; ++i ) {
+            final Transaction transaction = World.db().beginTransaction();
+            try {
+                transaction.setBatchMode(true);
+                transaction.setBatchSize(batchSize);
+                for(int j = i * batchSize ; j < Math.min((i + 1) * batchSize, worlds.size()); ++j) {
+                    World.db().update(worlds.get(j), transaction);
+                }
+                transaction.commit();
+            } finally {
+                transaction.end();
+            }
+        }
 
         return worlds;
     }
-
-}
+}

+ 15 - 0
frameworks/Java/play2-java/play2-java-ebean-hikaricp/app/utils/DatabaseExecutionContext.java

@@ -0,0 +1,15 @@
+package utils;
+
+import javax.inject.Inject;
+
+import akka.actor.ActorSystem;
+import play.libs.concurrent.CustomExecutionContext;
+
+public class DatabaseExecutionContext extends CustomExecutionContext {
+
+    @Inject
+    public DatabaseExecutionContext(final ActorSystem actorSystem) {
+        super(actorSystem, "database.dispatcher");
+    }
+
+}

+ 0 - 21
frameworks/Java/play2-java/play2-java-ebean-hikaricp/app/utils/Headers.java

@@ -1,21 +0,0 @@
-package utils;
-
-import java.util.concurrent.CompletionStage;
-import org.joda.time.DateTime;
-import org.joda.time.format.DateTimeFormat;
-import org.joda.time.format.DateTimeFormatter;
-import play.mvc.Action;
-import play.mvc.Http;
-import play.mvc.Result;
-
-public class Headers extends Action.Simple {
-
-    private static final DateTimeFormatter RFC_1123_DATE_TIME = DateTimeFormat.forPattern("EEE, dd MMM yyyy HH:mm:ss 'GMT'").withZoneUTC();
-
-    @Override
-    public CompletionStage<Result> call(Http.Context context) {
-        context.response().setHeader("Server", "Play2");
-        context.response().setHeader("Date", RFC_1123_DATE_TIME.print(new DateTime()));
-        return delegate.call(context);
-    }
-}

+ 0 - 8
frameworks/Java/play2-java/play2-java-ebean-hikaricp/app/utils/Predicate.java

@@ -1,8 +0,0 @@
-package utils;
-
-/**
- * Predicates for PredicatedActions.
- */
-public interface Predicate {
-    boolean condition();
-}

+ 0 - 26
frameworks/Java/play2-java/play2-java-ebean-hikaricp/app/utils/Predicated.java

@@ -1,26 +0,0 @@
-package utils;
-
-import play.mvc.With;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Declares a composing action that will check for a condition before deciding on whether to proceed with the request.
- */
-@With(PredicatedAction.class)
-@Target({ElementType.TYPE, ElementType.METHOD})
-@Retention(RetentionPolicy.RUNTIME)
-public @interface Predicated {
-    /**
-     * The condition.
-     */
-    Class<? extends Predicate> predicate();
-
-    /**
-     * The http status code to return if the condition fails.
-     */
-    int failed();
-}

+ 0 - 28
frameworks/Java/play2-java/play2-java-ebean-hikaricp/app/utils/PredicatedAction.java

@@ -1,28 +0,0 @@
-package utils;
-
-/**
- * A predicated action is one where a condition must be satisfied in order to proceed with the request. If the
- * condition is not satisfied then a supplied status result is yielded.
- */
-
-import com.google.inject.Injector;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.CompletionStage;
-import javax.inject.Inject;
-import play.mvc.Action;
-import play.mvc.Http;
-import play.mvc.Result;
-
-public class PredicatedAction extends Action<Predicated> {
-
-    @Inject private Injector injector;
-
-    @Override
-    public CompletionStage<Result> call(final Http.Context ctx) {
-        final Predicate p = injector.getInstance(configuration.predicate());
-        if (p.condition()) {
-            return delegate.call(ctx);
-        }
-        return CompletableFuture.supplyAsync(() -> status(configuration.failed()));
-    }
-}

+ 3 - 4
frameworks/Java/play2-java/play2-java-ebean-hikaricp/build.sbt

@@ -4,11 +4,10 @@ version := "1.0-SNAPSHOT"
 
 lazy val root = (project in file(".")).enablePlugins(PlayJava, PlayEbean)
 
-scalaVersion := "2.11.7"
+scalaVersion := "2.12.4"
 
 libraryDependencies ++= Seq(
+  guice,
   javaJdbc,
-  "mysql" % "mysql-connector-java" % "5.1.38"
+  "mysql" % "mysql-connector-java" % "5.1.44"
 )
-
-routesGenerator := InjectedRoutesGenerator

+ 55 - 48
frameworks/Java/play2-java/play2-java-ebean-hikaricp/conf/application.conf

@@ -4,66 +4,73 @@
 # Secret key
 # ~~~~~
 # The secret key is used to secure cryptographics functions.
-# If you deploy your application to several instances be sure to use the same key!
-play.crypto.secret="RItx1I:80?W@]8GAtPDuF8Ydd3mXM85p/<7og]Q;uBOdijQAauRDgu73B6`wQP59"
+play.http.secret.key = "RItx1I:80?W@]8GAtPDuF8Ydd3mXM85p/<7og]Q;uBOdijQAauRDgu73B6`wQP59"
 
 # The application languages
 # ~~~~~
-application.langs="en"
+play.i18n.langs = [ "en" ]
 
-# Global object class
-# ~~~~~
-# Define the Global object class for this application.
-# Default to Global in the root package.
-# global=Global
-
-# The dependency injection modules
-play.modules.enabled += "inject.AppModule"
+# Disable default filters
+play.filters.enabled = [ ]
 
-# Database configuration
-# ~~~~~ 
-# You can declare as many datasources as you want.
-# By convention, the default datasource is named `default`
-#
-# db.default.driver=org.h2.Driver
-# db.default.url="jdbc:h2:mem:play"
-# db.default.user=sa
-# db.default.password=
-#
-# You can expose this datasource via JNDI if needed (Useful for JPA)
-# db.default.jndiName=DefaultDS
+play.server.akka.server-header = "Play2"
 
-db.default.driver= com.mysql.jdbc.Driver
-db.default.url="jdbc:mysql://TFB-database:3306/hello_world?jdbcCompliantTruncation=false&elideSetAutoCommits=true&useLocalSessionState=true&cachePrepStmts=true&cacheCallableStmts=true&alwaysSendSetIsolation=false&prepStmtCacheSize=4096&cacheServerConfiguration=true&prepStmtCacheSqlLimit=2048&zeroDateTimeBehavior=convertToNull&traceProtocol=false&useUnbufferedInput=false&useReadAheadInput=false&maintainTimeStats=false&useServerPrepStmts&cacheRSMetadata=true"
-db.default.username=benchmarkdbuser
-db.default.password=benchmarkdbpass
-db.default.jndiName=DefaultDS
-jpa.default=defaultPersistenceUnit
+# Number of database connections
+# https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing
+# db connections = ((physical_core_count * 2) + effective_spindle_count)
+# The TechEmpower benchmark environment uses 2 x 4-Core E5520 CPUs in the database server
+# That is 8 physical cores
+# https://www.techempower.com/benchmarks/#section=environment
+fixedConnectionPool = 17
 
-db.default.partitionCount=4
+database.dispatcher {
+    executor = "thread-pool-executor"
+    throughput = 1
+    thread-pool-executor {
+        fixed-pool-size = ${fixedConnectionPool}
+    }
+}
 
-# The number of connections to create per partition. Setting this to
-# 5 with 3 partitions means you will have 15 unique connections to the
-# database..
-#
-# This value maps to the maximumPoolSize for HickariCP (db.default.partitionCount * db.default.maxConnectionsPerPartition)
-db.default.maxConnectionsPerPartition=64
-
-# The number of initial connections, per partition.
-#
-# This maps to the minimumIdle connections for HikariCP (db.default.partitionCount * db.default.minConnectionsPerPartition)
-db.default.minConnectionsPerPartition=64
-
-dbplugin=disabled
-
-# Evolutions
+# Database configuration
 # ~~~~~
-# You can disable evolutions if needed
-evolutionplugin=disabled
+# You can declare as many datasources as you want.
+# By convention, the default datasource is named `default`
+db {
+    default {
+        # https://github.com/brettwooldridge/HikariCP/wiki/MySQL-Configuration
+        url = "jdbc:mysql://TFB-database:3306/hello_world"
+        username = "benchmarkdbuser"
+        password = "benchmarkdbpass"
+        hikaricp {
+            dataSource {
+                cachePrepStmts=true
+                prepStmtCacheSize=250
+                prepStmtCacheSqlLimit=2048
+                useServerPrepStmts=true
+                useLocalSessionState=true
+                useLocalTransactionState=true
+                rewriteBatchedStatements=true
+                cacheResultSetMetadata=true
+                cacheServerConfiguration=true
+                cacheCallableStmts=true
+                callableStmtCacheSize=250
+                elideSetAutoCommits=true
+                maintainTimeStats=false
+                alwaysSendSetIsolation=false
+                zeroDateTimeBehavior="convertToNull"
+                traceProtocol=false
+                jdbcCompliantTruncation=false
+                useUnbufferedInput=false
+                #useReadAheadInput=false
+            }
+            maximumPoolSize = ${fixedConnectionPool}
+        }
+    }
+}
 
 # Ebean configuration
 # ~~~~~
 # You can declare as many Ebean servers as you want.
 # By convention, the default server is named `default`
 #
-ebean.default="models.*"
+ebean.default = [ "models.*" ]

+ 8 - 2
frameworks/Java/play2-java/play2-java-ebean-hikaricp/conf/logback.xml

@@ -4,10 +4,16 @@
 
   <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
     <encoder>
-      <pattern>%coloredLevel - %logger - %message%n%xException</pattern>
+      <pattern>%coloredLevel %logger{15} - %message%n%xException{10}</pattern>
     </encoder>
   </appender>
 
+  <appender name="ASYNCSTDOUT" class="ch.qos.logback.classic.AsyncAppender">
+    <queueSize>500</queueSize>
+    <discardingThreshold>0</discardingThreshold>
+    <appender-ref ref="STDOUT" />
+  </appender>
+
   <!--
     The logger name is typically the Java/Scala package name.
     This configures the log level to log at for a package and its children packages.
@@ -16,7 +22,7 @@
   <logger name="application" level="INFO" />
 
   <root level="ERROR">
-    <appender-ref ref="STDOUT" />
+    <appender-ref ref="ASYNCSTDOUT" />
   </root>
 
 </configuration>

+ 2 - 7
frameworks/Java/play2-java/play2-java-ebean-hikaricp/conf/routes

@@ -2,12 +2,7 @@
 # This file defines all application routes (Higher priority routes first)
 # ~~~~
 
-# Home page
 GET        /db                  controllers.Application.db()
-GET        /queries             controllers.Application.queries(queries ?= "1")
+GET        /queries             controllers.Application.queries(queries:String ?= "1")
 GET        /fortunes            controllers.Application.fortunes()
-GET        /update              controllers.Application.update(queries ?= "1")
-
-
-# Map static resources from the /public folder to the /assets URL path
-GET        /assets/*file        controllers.Assets.at(path="/public", file)
+GET        /update              controllers.Application.update(queries:String ?= "1")

+ 1 - 1
frameworks/Java/play2-java/play2-java-ebean-hikaricp/project/build.properties

@@ -1 +1 @@
-sbt.version=0.13.16
+sbt.version=1.0.2

+ 3 - 2
frameworks/Java/play2-java/play2-java-ebean-hikaricp/project/plugins.sbt

@@ -1,2 +1,3 @@
-addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.5.14")
-addSbtPlugin("com.typesafe.sbt" % "sbt-play-ebean" % "3.0.0")
+addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.6.7")
+
+addSbtPlugin("com.typesafe.sbt" % "sbt-play-ebean" % "4.0.6")

+ 8 - 11
frameworks/Java/play2-java/play2-java-ebean-hikaricp/source_code

@@ -1,11 +1,8 @@
-./play-java-jpa/app/
-./play-java-jpa/app/controllers
-./play-java-jpa/app/controllers/Application.java
-./play-java-jpa/app/utils
-./play-java-jpa/app/utils/Headers.java
-./play-java-jpa/app/utils/Predicate.java
-./play-java-jpa/app/utils/PredicatedAction.java
-./play-java-jpa/app/utils/Predicated.java
-./play-java-jpa/app/models
-./play-java-jpa/app/models/World.java
-./play-java-jpa/app/models/Fortune.java
+./play2-java-ebean-hikaricp/app/
+./play2-java-ebean-hikaricp/app/controllers
+./play2-java-ebean-hikaricp/app/controllers/Application.java
+./play2-java-ebean-hikaricp/app/utils
+./play2-java-ebean-hikaricp/app/utils/DatabaseExecutionContext.java
+./play2-java-ebean-hikaricp/app/models
+./play2-java-ebean-hikaricp/app/models/World.java
+./play2-java-ebean-hikaricp/app/models/Fortune.java

+ 1 - 14
frameworks/Java/play2-java/play2-java-jpa-hikaricp/README.md

@@ -2,35 +2,22 @@
 
 This is the Play portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
 
-### JSON Encoding Test
-
-* [JSON test controller](app/controllers/Application.java)
-
 ### Data-Store/Database Mapping Test
 
 * [Database test controller](app/controllers/Application.java)
 * [Database World test model](app/models/World.java)
 * [Database Fortune test model](app/models/Fortune.java)
 
-### Plain Text Test
-
-* [Plain text test controller](app/controllers/Application.java)
-
 ## Infrastructure Software Versions
 The tests were run with:
 
 * Java 8
-* [Play 2.4.2](https://www.playframework.com/)
+* [Play 2.6.7](https://www.playframework.com/)
 
 ## Test URLs
-### JSON Encoding Test
-
-* http://localhost/json
-
 ### Data-Store/Database Mapping Test
 
 * http://localhost/db
 * http://localhost/queries?queries=10
 * http://localhost/fortunes
 * http://localhost/update?queries=10
-

+ 38 - 72
frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/controllers/Application.java

@@ -1,78 +1,45 @@
 package controllers;
 
-import akka.dispatch.ExecutionContexts;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ObjectNode;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.ThreadLocalRandom;
+
+import javax.inject.Inject;
+
 import models.Fortune;
 import models.World;
-import play.Play;
-import play.core.NamedThreadFactory;
-import play.libs.F;
+import play.db.jpa.JPAApi;
 import play.libs.Json;
 import play.mvc.Controller;
 import play.mvc.Result;
-import play.mvc.With;
-import scala.concurrent.ExecutionContext;
-import utils.Headers;
-import utils.Predicate;
-import utils.Predicated;
-
-import java.util.*;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ThreadLocalRandom;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
+import utils.DatabaseExecutionContext;
 
-@With(Headers.class)
 public class Application extends Controller {
 
-    private static final int TEST_DATABASE_ROWS = 10000;
-
-    private static final int partitionCount = Play.application().configuration().getInt("db.default.partitionCount");
-    private static final int maxConnections =
-            partitionCount * Play.application().configuration().getInt("db.default.maxConnectionsPerPartition");
-    private static final int minConnections =
-            partitionCount * Play.application().configuration().getInt("db.default.minConnectionsPerPartition");
-
-    private static final ThreadPoolExecutor tpe = new ThreadPoolExecutor(minConnections, maxConnections,
-            0L, TimeUnit.MILLISECONDS,
-            new LinkedBlockingQueue<>(),
-            new NamedThreadFactory("dbEc"));
-    private static final ExecutionContext dbEc = ExecutionContexts.fromExecutorService(tpe);
+    private final JPAApi jpa;
+    private final DatabaseExecutionContext dbEc;
 
-    public static class Message {
-        public final String message = "Hello, World!";
-    }
-
-    public Result json() {
-        return ok(Json.toJson(new Message()));
-    }
-
-    // If the thread-pool used by the database grows too large then our server
-    // is probably struggling, and we should start dropping requests. Set
-    // the max size of our queue something above the number of concurrent
-    // connections that we need to handle.
-    public static class IsDbAvailable implements Predicate {
-        @Override
-        public boolean condition() {
-            return tpe.getQueue().size() <= 1024;
-        }
+    @Inject
+    public Application(final JPAApi jpa, final DatabaseExecutionContext dbEc) {
+        this.jpa = jpa;
+        this.dbEc = dbEc;
     }
 
-    @Predicated(predicate = IsDbAvailable.class, failed = SERVICE_UNAVAILABLE)
-    public F.Promise<Result> db() {
-        return getRandomWorlds(1).map(worlds -> ok(Json.toJson(worlds.get(0))));
+    public CompletionStage<Result> db() {
+        return getRandomWorlds(1).thenApply(worlds -> ok(Json.toJson(worlds.get(0))));
     }
 
-    @Predicated(predicate = IsDbAvailable.class, failed = SERVICE_UNAVAILABLE)
-    public F.Promise<Result> queries(final String queryCountString) {
-        return getRandomWorlds(queryCount(queryCountString)).map(worlds -> ok(Json.toJson(worlds)));
+    public CompletionStage<Result> queries(final String queries) {
+        return getRandomWorlds(queryCount(queries)).thenApply(worlds -> ok(Json.toJson(worlds)));
     }
 
-    @Predicated(predicate = IsDbAvailable.class, failed = SERVICE_UNAVAILABLE)
-    public F.Promise<Result> fortunes() {
-        return F.Promise.promise(() -> {
-            List<Fortune> fortunes = Fortune.findAll();
+    public CompletionStage<Result> fortunes() {
+        return CompletableFuture.supplyAsync(() -> {
+            final List<Fortune> fortunes = Fortune.findAll(this.jpa);
             fortunes.add(new Fortune("Additional fortune added at request time."));
             Collections.sort(fortunes, (f1, f2) -> f1.message.compareTo(f2.message));
 
@@ -80,24 +47,23 @@ public class Application extends Controller {
         }, dbEc);
     }
 
-    @Predicated(predicate = IsDbAvailable.class, failed = SERVICE_UNAVAILABLE)
-    public F.Promise<Result> update(final String queryCountString) {
-        return getRandomWorlds(queryCount(queryCountString)).map(worlds -> {
-            Random random = ThreadLocalRandom.current();
-            for (World world : worlds) {
+    public CompletionStage<Result> update(final String queries) {
+        return getRandomWorlds(queryCount(queries)).thenApplyAsync(worlds -> {
+            final Random random = ThreadLocalRandom.current();
+            for (final World world : worlds) {
                 world.randomNumber = (long) (random.nextInt(10000) + 1);
             }
 
-            List<World> updatedWorlds = World.save(worlds);
+            final List<World> updatedWorlds = World.save(worlds, this.jpa);
             return ok(Json.toJson(updatedWorlds));
         }, dbEc);
     }
 
-    private int queryCount(String queryCountString) {
+    private int queryCount(final String queryCountString) {
         int queryCount;
         try {
             queryCount = Integer.parseInt(queryCountString, 10);
-        } catch (NumberFormatException e) {
+        } catch (final NumberFormatException e) {
             queryCount = 1;
         }
         if (queryCount < 1) {
@@ -109,13 +75,13 @@ public class Application extends Controller {
         return queryCount;
     }
 
-    private F.Promise<List<World>> getRandomWorlds(final int n) {
-        return F.Promise.promise(() -> {
-            Random random = ThreadLocalRandom.current();
-            List<World> worlds = new ArrayList<>(n);
+    private CompletionStage<List<World>> getRandomWorlds(final int n) {
+        return CompletableFuture.supplyAsync(() -> {
+            final Random random = ThreadLocalRandom.current();
+            final List<World> worlds = new ArrayList<>(n);
             for (int i = 0; i < n; ++i) {
-                long randomId = random.nextInt(TEST_DATABASE_ROWS) + 1;
-                World world = World.findById(randomId);
+                long randomId = random.nextInt(10000) + 1;
+                final World world = World.findById(randomId, this.jpa);
                 worlds.add(world);
             }
             return worlds;

+ 8 - 7
frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/models/Fortune.java

@@ -1,11 +1,12 @@
 package models;
 
-import play.db.jpa.JPA;
+import java.util.List;
 
 import javax.persistence.Entity;
 import javax.persistence.Id;
 import javax.persistence.criteria.CriteriaQuery;
-import java.util.List;
+
+import play.db.jpa.JPAApi;
 
 @Entity
 public class Fortune {
@@ -18,15 +19,15 @@ public class Fortune {
     public Fortune() {
     }
 
-    public Fortune(String message) {
+    public Fortune(final String message) {
         this.message = message;
     }
 
-    public static List<Fortune> findAll() throws Throwable {
-        return JPA.withTransaction("default", true, () -> {
-            CriteriaQuery<Fortune> criteria = JPA.em().getCriteriaBuilder().createQuery(Fortune.class);
+    public static List<Fortune> findAll(final JPAApi jpa) {
+        return jpa.withTransaction("default", true, em -> {
+            final CriteriaQuery<Fortune> criteria = em.getCriteriaBuilder().createQuery(Fortune.class);
             criteria.select(criteria.from(Fortune.class));
-            return JPA.em().createQuery(criteria).getResultList();
+            return em.createQuery(criteria).getResultList();
         });
     }
 }

+ 19 - 7
frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/models/World.java

@@ -1,11 +1,14 @@
 package models;
 
-import play.db.jpa.JPA;
+import java.util.List;
 
 import javax.persistence.Column;
 import javax.persistence.Entity;
 import javax.persistence.Id;
-import java.util.List;
+
+import org.hibernate.Session;
+
+import play.db.jpa.JPAApi;
 
 @Entity
 public class World {
@@ -16,13 +19,22 @@ public class World {
     @Column(name = "randomNumber")
     public Long randomNumber;
 
-    public static World findById(final Long id) throws Throwable {
-        return JPA.withTransaction("default", true, () -> JPA.em().find(World.class, id));
+    public static World findById(final Long id, final JPAApi jpa) {
+        return jpa.withTransaction("default", true, em -> em.find(World.class, id));
     }
 
-    public static List<World> save(final List<World> worlds) throws Throwable {
-        for (final World world : worlds) {
-            JPA.withTransaction("default", false, () -> JPA.em().merge(world));
+    public static List<World> save(final List<World> worlds, final JPAApi jpa) {
+        final int batchSize = 25;
+        final int batches = ((worlds.size() / batchSize) + 1);
+        for ( int i = 0 ; i < batches ; ++i ) {
+            final int index = i;
+            jpa.withTransaction("default", false, em -> {
+                em.unwrap(Session.class).setJdbcBatchSize(25);
+                for(int j = index * batchSize ; j < Math.min((index + 1) * batchSize, worlds.size()); ++j) {
+                    em.merge(worlds.get(j));
+                }
+                return null;
+            });
         }
 
         return worlds;

+ 15 - 0
frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/utils/DatabaseExecutionContext.java

@@ -0,0 +1,15 @@
+package utils;
+
+import javax.inject.Inject;
+
+import akka.actor.ActorSystem;
+import play.libs.concurrent.CustomExecutionContext;
+
+public class DatabaseExecutionContext extends CustomExecutionContext {
+
+    @Inject
+    public DatabaseExecutionContext(final ActorSystem actorSystem) {
+        super(actorSystem, "database.dispatcher");
+    }
+
+}

+ 0 - 21
frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/utils/Headers.java

@@ -1,21 +0,0 @@
-package utils;
-
-import org.joda.time.DateTime;
-import org.joda.time.format.DateTimeFormat;
-import org.joda.time.format.DateTimeFormatter;
-import play.libs.F;
-import play.mvc.Action;
-import play.mvc.Http;
-import play.mvc.Result;
-
-public class Headers extends Action.Simple {
-
-    private static final DateTimeFormatter RFC_1123_DATE_TIME = DateTimeFormat.forPattern("EEE, dd MMM yyyy HH:mm:ss 'GMT'").withZoneUTC();
-
-    @Override
-    public F.Promise<Result> call(Http.Context context) throws Throwable {
-        context.response().setHeader("Server", "Play2");
-        context.response().setHeader("Date", RFC_1123_DATE_TIME.print(new DateTime()));
-        return delegate.call(context);
-    }
-}

+ 0 - 8
frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/utils/Predicate.java

@@ -1,8 +0,0 @@
-package utils;
-
-/**
- * Predicates for PredicatedActions.
- */
-public interface Predicate {
-    boolean condition();
-}

+ 0 - 26
frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/utils/Predicated.java

@@ -1,26 +0,0 @@
-package utils;
-
-import play.mvc.With;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Declares a composing action that will check for a condition before deciding on whether to proceed with the request.
- */
-@With(PredicatedAction.class)
-@Target({ElementType.TYPE, ElementType.METHOD})
-@Retention(RetentionPolicy.RUNTIME)
-public @interface Predicated {
-    /**
-     * The condition.
-     */
-    Class<? extends Predicate> predicate();
-
-    /**
-     * The http status code to return if the condition fails.
-     */
-    int failed();
-}

+ 0 - 23
frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/utils/PredicatedAction.java

@@ -1,23 +0,0 @@
-package utils;
-
-/**
- * A predicated action is one where a condition must be satisfied in order to proceed with the request. If the
- * condition is not satisfied then a supplied status result is yielded.
- */
-
-import play.libs.F;
-import play.mvc.Action;
-import play.mvc.Http;
-import play.mvc.Result;
-
-public class PredicatedAction extends Action<Predicated> {
-    @Override
-    public F.Promise<Result> call(final Http.Context ctx) throws Throwable {
-        final Predicate p = configuration.predicate().newInstance();
-        if (p.condition()) {
-            return delegate.call(ctx);
-        } else {
-            return F.Promise.<Result>pure(status(configuration.failed()));
-        }
-    }
-}

+ 5 - 7
frameworks/Java/play2-java/play2-java-jpa-hikaricp/build.sbt

@@ -1,18 +1,16 @@
-name := """play2-java-jpa-hikaricp"""
+name := "play2-java-jpa-hikaricp"
 
 version := "1.0-SNAPSHOT"
 
 lazy val root = (project in file(".")).enablePlugins(PlayJava)
 
-scalaVersion := "2.11.7"
+scalaVersion := "2.12.4"
 
 libraryDependencies ++= Seq(
-  javaJdbc,
+  guice,
   javaJpa,
-  "mysql" % "mysql-connector-java" % "5.1.38",
-  "org.hibernate" % "hibernate-entitymanager" % "5.0.1.Final"
+  "mysql" % "mysql-connector-java" % "5.1.44",
+  "org.hibernate" % "hibernate-core" % "5.2.12.Final"
 )
 
-routesGenerator := InjectedRoutesGenerator
-
 PlayKeys.externalizeResources := false

+ 1 - 0
frameworks/Java/play2-java/play2-java-jpa-hikaricp/conf/META-INF/persistence.xml

@@ -6,6 +6,7 @@
     <persistence-unit name="defaultPersistenceUnit" transaction-type="RESOURCE_LOCAL">
         <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
         <non-jta-data-source>DefaultDS</non-jta-data-source>
+        <validation-mode>NONE</validation-mode>
         <properties>
             <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
         </properties>

+ 55 - 58
frameworks/Java/play2-java/play2-java-jpa-hikaricp/conf/application.conf

@@ -4,71 +4,68 @@
 # Secret key
 # ~~~~~
 # The secret key is used to secure cryptographics functions.
-#
-# This must be changed for production, but we recommend not changing it in this file.
-#
-# See http://www.playframework.com/documentation/latest/ApplicationSecret for more details
-play.crypto.secret="`o0VB@vXStsF:ffwM5ZZ_r:GYkm96QM[nRUJLpEbI8hwLUdV;N<:UyUWI;lf/XP`"
+play.http.secret.key = "`o0VB@vXStsF:ffwM5ZZ_r:GYkm96QM[nRUJLpEbI8hwLUdV;N<:UyUWI;lf/XP`"
 
 # The application languages
 # ~~~~~
-application.langs="en"
+play.i18n.langs = [ "en" ]
 
-# Global object class
-# ~~~~~
-# Define the Global object class for this application.
-# Default to Global in the root package.
-# application.global=Global
+# Disable default filters
+play.filters.enabled = [ ]
 
-# Router
-# ~~~~~
-# Define the Router object to use for this application.
-# This router will be looked up first when the application is starting up,
-# so make sure this is the entry point.
-# Furthermore, it's assumed your route file is named properly.
-# So for an application router like `conf/my.application.Router`,
-# you may need to define a router file `my.application.routes`.
-# Default to Routes in the root package (and `conf/routes`)
-# application.router=my.application.Routes
+play.server.akka.server-header = "Play2"
+
+# Number of database connections
+# https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing
+# db connections = ((physical_core_count * 2) + effective_spindle_count)
+# The TechEmpower benchmark environment uses 2 x 4-Core E5520 CPUs in the database server
+# That is 8 physical cores
+# https://www.techempower.com/benchmarks/#section=environment
+fixedConnectionPool = 17
+
+database.dispatcher {
+    executor = "thread-pool-executor"
+    throughput = 1
+    thread-pool-executor {
+        fixed-pool-size = ${fixedConnectionPool}
+    }
+}
 
 # Database configuration
 # ~~~~~
 # You can declare as many datasources as you want.
 # By convention, the default datasource is named `default`
-#
-# db.default.driver=org.h2.Driver
-# db.default.url="jdbc:h2:mem:play"
-# db.default.user=sa
-# db.default.password=""
-#
-# You can expose this datasource via JNDI if needed (Useful for JPA)
-# db.default.jndiName=DefaultDS
-
-db.default.driver= com.mysql.jdbc.Driver
-db.default.url="jdbc:mysql://TFB-database:3306/hello_world?jdbcCompliantTruncation=false&elideSetAutoCommits=true&useLocalSessionState=true&cachePrepStmts=true&cacheCallableStmts=true&alwaysSendSetIsolation=false&prepStmtCacheSize=4096&cacheServerConfiguration=true&prepStmtCacheSqlLimit=2048&zeroDateTimeBehavior=convertToNull&traceProtocol=false&useUnbufferedInput=false&useReadAheadInput=false&maintainTimeStats=false&useServerPrepStmts&cacheRSMetadata=true"
-db.default.username=benchmarkdbuser
-db.default.password=benchmarkdbpass
-db.default.jndiName=DefaultDS
-jpa.default=defaultPersistenceUnit
-
-db.default.partitionCount=4
-
-# The number of connections to create per partition. Setting this to
-# 5 with 3 partitions means you will have 15 unique connections to the
-# database..
-#
-# This value maps to the maximumPoolSize for HickariCP (db.default.partitionCount * db.default.maxConnectionsPerPartition)
-db.default.maxConnectionsPerPartition=64
-
-# The number of initial connections, per partition.
-#
-# This maps to the minimumIdle connections for HikariCP (db.default.partitionCount * db.default.minConnectionsPerPartition)
-db.default.minConnectionsPerPartition=64
-
-dbplugin=disabled
-
-# Evolutions
-# ~~~~~
-# You can disable evolutions if needed
-evolutionplugin=disabled
-
+db {
+    default {
+        # https://github.com/brettwooldridge/HikariCP/wiki/MySQL-Configuration
+        url = "jdbc:mysql://TFB-database:3306/hello_world"
+        username = "benchmarkdbuser"
+        password = "benchmarkdbpass"
+        hikaricp {
+            dataSource {
+                cachePrepStmts=true
+                prepStmtCacheSize=250
+                prepStmtCacheSqlLimit=2048
+                useServerPrepStmts=true
+                useLocalSessionState=true
+                useLocalTransactionState=true
+                rewriteBatchedStatements=true
+                cacheResultSetMetadata=true
+                cacheServerConfiguration=true
+                cacheCallableStmts=true
+                callableStmtCacheSize=250
+                elideSetAutoCommits=true
+                maintainTimeStats=false
+                alwaysSendSetIsolation=false
+                zeroDateTimeBehavior="convertToNull"
+                traceProtocol=false
+                jdbcCompliantTruncation=false
+                useUnbufferedInput=false
+                #useReadAheadInput=false
+            }
+            maximumPoolSize = ${fixedConnectionPool}
+        }
+        jndiName = DefaultDS
+    }
+}
+jpa.default = defaultPersistenceUnit

+ 9 - 3
frameworks/Java/play2-java/play2-java-jpa-hikaricp/conf/logback.xml

@@ -1,13 +1,19 @@
 <configuration>
     
-  <conversionRule conversionWord="coloredLevel" converterClass="play.api.Logger$ColoredLevel" />
+  <conversionRule conversionWord="coloredLevel" converterClass="play.api.libs.logback.ColoredLevel" />
 
   <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
     <encoder>
-      <pattern>%coloredLevel - %logger - %message%n%xException</pattern>
+      <pattern>%coloredLevel %logger{15} - %message%n%xException{10}</pattern>
     </encoder>
   </appender>
 
+  <appender name="ASYNCSTDOUT" class="ch.qos.logback.classic.AsyncAppender">
+    <queueSize>500</queueSize>
+    <discardingThreshold>0</discardingThreshold>
+    <appender-ref ref="STDOUT" />
+  </appender>
+
   <!--
     The logger name is typically the Java/Scala package name.
     This configures the log level to log at for a package and its children packages.
@@ -16,7 +22,7 @@
   <logger name="application" level="INFO" />
 
   <root level="ERROR">
-    <appender-ref ref="STDOUT" />
+    <appender-ref ref="ASYNCSTDOUT" />
   </root>
 
 </configuration>

+ 2 - 6
frameworks/Java/play2-java/play2-java-jpa-hikaricp/conf/routes

@@ -2,11 +2,7 @@
 # This file defines all application routes (Higher priority routes first)
 # ~~~~
 
-GET        /json                controllers.Application.json()
 GET        /db                  controllers.Application.db()
-GET        /queries             controllers.Application.queries(queries ?= "1")
+GET        /queries             controllers.Application.queries(queries:String ?= "1")
 GET        /fortunes            controllers.Application.fortunes()
-GET        /update              controllers.Application.update(queries ?= "1")
-
-# Map static resources from the /public folder to the /assets URL path
-GET        /assets/*file        controllers.Assets.at(path="/public", file)
+GET        /update              controllers.Application.update(queries:String ?= "1")

+ 1 - 1
frameworks/Java/play2-java/play2-java-jpa-hikaricp/project/build.properties

@@ -1 +1 @@
-sbt.version=0.13.16
+sbt.version=1.0.2

+ 1 - 1
frameworks/Java/play2-java/play2-java-jpa-hikaricp/project/plugins.sbt

@@ -1 +1 @@
-addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.4.2")
+addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.6.7")

+ 8 - 11
frameworks/Java/play2-java/play2-java-jpa-hikaricp/source_code

@@ -1,11 +1,8 @@
-./play-java-jpa/app/
-./play-java-jpa/app/controllers
-./play-java-jpa/app/controllers/Application.java
-./play-java-jpa/app/utils
-./play-java-jpa/app/utils/Headers.java
-./play-java-jpa/app/utils/Predicate.java
-./play-java-jpa/app/utils/PredicatedAction.java
-./play-java-jpa/app/utils/Predicated.java
-./play-java-jpa/app/models
-./play-java-jpa/app/models/World.java
-./play-java-jpa/app/models/Fortune.java
+./play2-java-jpa-hikaricp/app/
+./play2-java-jpa-hikaricp/app/controllers
+./play2-java-jpa-hikaricp/app/controllers/Application.java
+./play2-java-jpa-hikaricp/app/utils
+./play2-java-jpa-hikaricp/app/utils/DatabaseExecutionContext.java
+./play2-java-jpa-hikaricp/app/models
+./play2-java-jpa-hikaricp/app/models/World.java
+./play2-java-jpa-hikaricp/app/models/Fortune.java

+ 1 - 1
frameworks/Java/play2-java/play2-java/README.md

@@ -10,7 +10,7 @@ This is the Play portion of a [benchmarking test suite](../) comparing a variety
 The tests were run with:
 
 * Java 8
-* [Play 2.6.6](http://http://www.playframework.com/)
+* [Play 2.6.7](https://www.playframework.com/)
 
 ## Test URLs
 ### JSON Encoding Test

+ 3 - 7
frameworks/Java/play2-java/play2-java/app/controllers/Application.java

@@ -1,14 +1,10 @@
 package controllers;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ObjectNode;
+import play.libs.Json;
 import play.mvc.Controller;
+import play.mvc.Http.MimeTypes;
 import play.mvc.Result;
-import play.mvc.With;
-import play.libs.Json;
-import utils.Headers;
 
-@With(Headers.class)
 public class Application extends Controller {
 
     public static class Message {
@@ -20,7 +16,7 @@ public class Application extends Controller {
     }
 
     public Result plainText() {
-        return ok("Hello, World!");
+        return ok("Hello, World!").as(MimeTypes.TEXT);
     }
 
 }

+ 0 - 21
frameworks/Java/play2-java/play2-java/app/utils/Headers.java

@@ -1,21 +0,0 @@
-package utils;
-
-import java.util.concurrent.CompletionStage;
-import org.joda.time.DateTime;
-import org.joda.time.format.DateTimeFormat;
-import org.joda.time.format.DateTimeFormatter;
-import play.mvc.Action;
-import play.mvc.Http;
-import play.mvc.Result;
-
-public class Headers extends Action.Simple {
-
-    private static final DateTimeFormatter RFC_1123_DATE_TIME = DateTimeFormat.forPattern("EEE, dd MMM yyyy HH:mm:ss 'GMT'").withZoneUTC();
-
-    @Override
-    public CompletionStage<Result> call(Http.Context context) {
-        context.response().setHeader("Server", "Play2");
-        context.response().setHeader("Date", RFC_1123_DATE_TIME.print(new DateTime()));
-        return delegate.call(context);
-    }
-}

+ 4 - 5
frameworks/Java/play2-java/play2-java/build.sbt

@@ -1,10 +1,9 @@
 name := "play2-java"
-version := "1.0-SNAPSHOT"
-scalaVersion := "2.12.4"
-
-libraryDependencies += guice
 
-routesGenerator := InjectedRoutesGenerator
+version := "1.0-SNAPSHOT"
 
 lazy val root = (project in file(".")).enablePlugins(PlayJava)
 
+scalaVersion := "2.12.4"
+
+libraryDependencies += guice

+ 5 - 4
frameworks/Java/play2-java/play2-java/conf/application.conf

@@ -4,12 +4,13 @@
 # Secret key
 # ~~~~~
 # The secret key is used to secure cryptographics functions.
-# If you deploy your application to several instances be sure to use the same key!
-play.http.secret.key="RItx1I:80?W@]8GAtPDuF8Ydd3mXM85p/<7og]Q;uBOdijQAauRDgu73B6`wQP59"
+play.http.secret.key = "RItx1I:80?W@]8GAtPDuF8Ydd3mXM85p/<7og]Q;uBOdijQAauRDgu73B6`wQP59"
 
 # The application languages
 # ~~~~~
-application.langs="en"
+play.i18n.langs = [ "en" ]
 
 # Disable default filters
-play.filters.enabled=[]
+play.filters.enabled = [ ]
+
+play.server.akka.server-header = "Play2"

+ 9 - 3
frameworks/Java/play2-java/play2-java/conf/logback.xml

@@ -1,13 +1,19 @@
 <configuration>
     
-  <conversionRule conversionWord="coloredLevel" converterClass="play.api.Logger$ColoredLevel" />
+  <conversionRule conversionWord="coloredLevel" converterClass="play.api.libs.logback.ColoredLevel" />
 
   <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
     <encoder>
-      <pattern>%coloredLevel - %logger - %message%n%xException</pattern>
+      <pattern>%coloredLevel %logger{15} - %message%n%xException{10}</pattern>
     </encoder>
   </appender>
 
+  <appender name="ASYNCSTDOUT" class="ch.qos.logback.classic.AsyncAppender">
+    <queueSize>500</queueSize>
+    <discardingThreshold>0</discardingThreshold>
+    <appender-ref ref="STDOUT" />
+  </appender>
+
   <!--
     The logger name is typically the Java/Scala package name.
     This configures the log level to log at for a package and its children packages.
@@ -16,7 +22,7 @@
   <logger name="application" level="INFO" />
 
   <root level="ERROR">
-    <appender-ref ref="STDOUT" />
+    <appender-ref ref="ASYNCSTDOUT" />
   </root>
 
 </configuration>

+ 2 - 6
frameworks/Java/play2-java/play2-java/conf/routes

@@ -2,9 +2,5 @@
 # This file defines all application routes (Higher priority routes first)
 # ~~~~
 
-# Home page
-GET        /json                controllers.Application.json
-GET        /plaintext           controllers.Application.plainText
-
-# Map static resources from the /public folder to the /assets URL path
-GET        /assets/*file        controllers.Assets.at(path="/public", file)
+GET        /json                controllers.Application.json()
+GET        /plaintext           controllers.Application.plainText()

+ 1 - 1
frameworks/Java/play2-java/play2-java/project/build.properties

@@ -1 +1 @@
-sbt.version=0.13.16
+sbt.version=1.0.2

+ 1 - 1
frameworks/Java/play2-java/play2-java/project/plugins.sbt

@@ -1 +1 @@
-addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.6.6")
+addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.6.7")

+ 3 - 3
frameworks/Java/play2-java/play2-java/source_code

@@ -1,3 +1,3 @@
-./play-java/app/
-./play-java/app/controllers
-./play-java/app/controllers/Application.java
+./play2-java/app/
+./play2-java/app/controllers
+./play2-java/app/controllers/Application.java