瀏覽代碼

Clean up play2-scala projects (#3069)

Matthias Kurz 7 年之前
父節點
當前提交
4a38790a07
共有 27 個文件被更改,包括 177 次插入346 次删除
  1. 12 15
      frameworks/Scala/play2-scala/benchmark_config.json
  2. 4 16
      frameworks/Scala/play2-scala/play2-scala-anorm/app/controllers/Application.scala
  3. 1 2
      frameworks/Scala/play2-scala/play2-scala-anorm/app/models/Fortune.scala
  4. 1 2
      frameworks/Scala/play2-scala/play2-scala-anorm/app/models/World.scala
  5. 8 23
      frameworks/Scala/play2-scala/play2-scala-anorm/app/utils/DbOperation.scala
  6. 3 2
      frameworks/Scala/play2-scala/play2-scala-anorm/build.sbt
  7. 52 52
      frameworks/Scala/play2-scala/play2-scala-anorm/conf/application.conf
  8. 4 10
      frameworks/Scala/play2-scala/play2-scala-anorm/conf/routes
  9. 0 4
      frameworks/Scala/play2-scala/play2-scala-anorm/project/plugins.sbt
  10. 2 5
      frameworks/Scala/play2-scala/play2-scala-reactivemongo/app/AppLoader.scala
  11. 5 18
      frameworks/Scala/play2-scala/play2-scala-reactivemongo/app/controllers/Application.scala
  12. 2 4
      frameworks/Scala/play2-scala/play2-scala-reactivemongo/build.sbt
  13. 9 36
      frameworks/Scala/play2-scala/play2-scala-reactivemongo/conf/application.conf
  14. 2 8
      frameworks/Scala/play2-scala/play2-scala-reactivemongo/conf/routes
  15. 0 1
      frameworks/Scala/play2-scala/play2-scala-reactivemongo/project/plugins.sbt
  16. 4 17
      frameworks/Scala/play2-scala/play2-scala-slick/app/controllers/Application.scala
  17. 1 2
      frameworks/Scala/play2-scala/play2-scala-slick/app/models/Fortune.scala
  18. 1 2
      frameworks/Scala/play2-scala/play2-scala-slick/app/models/World.scala
  19. 3 3
      frameworks/Scala/play2-scala/play2-scala-slick/build.sbt
  20. 44 44
      frameworks/Scala/play2-scala/play2-scala-slick/conf/application.conf
  21. 4 10
      frameworks/Scala/play2-scala/play2-scala-slick/conf/routes
  22. 0 4
      frameworks/Scala/play2-scala/play2-scala-slick/project/plugins.sbt
  23. 2 4
      frameworks/Scala/play2-scala/play2-scala/app/controllers/Application.scala
  24. 6 6
      frameworks/Scala/play2-scala/play2-scala/build.sbt
  25. 3 52
      frameworks/Scala/play2-scala/play2-scala/conf/application.conf
  26. 4 0
      frameworks/Scala/play2-scala/play2-scala/conf/routes
  27. 0 4
      frameworks/Scala/play2-scala/play2-scala/project/plugins.sbt

+ 12 - 15
frameworks/Scala/play2-scala/benchmark_config.json

@@ -7,6 +7,7 @@
         "setup_file": "setup_scala", 
         "framework": "play2", 
         "language": "Scala", 
+        "flavor": "None",
         "orm": "Raw", 
         "os": "Linux", 
         "database": "None", 
@@ -18,7 +19,7 @@
         "notes": "", 
         "versus": "akka-http", 
         "port": "9000", 
-        "json_url": "/json",
+        "json_url": "/json", 
         "plaintext_url": "/plaintext"
       }, 
       "anorm-linux": {
@@ -26,6 +27,7 @@
         "setup_file": "setup_scala_anorm", 
         "framework": "play2", 
         "language": "Scala", 
+        "flavor": "None",
         "orm": "Full", 
         "os": "Linux", 
         "database": "MySQL", 
@@ -40,15 +42,14 @@
         "db_url": "/db", 
         "query_url": "/queries?queries=", 
         "fortune_url": "/fortunes", 
-        "update_url": "/update?queries=",
-        "json_url": "/json",
-        "plaintext_url": "/plaintext"
+        "update_url": "/update?queries="
       }, 
       "anorm-windows": {
         "display_name": "play2-scala-anorm-windows", 
         "setup_file": "setup_scala_anorm", 
         "framework": "play2", 
         "language": "Scala", 
+        "flavor": "None",
         "orm": "Full", 
         "os": "Windows", 
         "database": "MySQL", 
@@ -63,15 +64,14 @@
         "db_url": "/db", 
         "query_url": "/queries?queries=", 
         "fortune_url": "/fortunes", 
-        "update_url": "/update?queries=",
-        "json_url": "/json",
-        "plaintext_url": "/plaintext"
-      }, 
+        "update_url": "/update?queries="
+      },
       "reactivemongo": {
         "display_name": "play2-scala-reactivemongo", 
         "setup_file": "setup_scala_reactivemongo", 
         "framework": "play2", 
         "language": "Scala", 
+        "flavor": "None",
         "orm": "Full", 
         "os": "Linux", 
         "database": "MongoDB", 
@@ -87,15 +87,14 @@
         "db_url": "/db", 
         "query_url": "/queries?queries=",
         "fortune_url": "/fortunes", 
-        "update_url": "/update?queries=",
-        "json_url": "/json",
-        "plaintext_url": "/plaintext"
-      }, 
+        "update_url": "/update?queries="
+      },
       "slick": {
         "display_name": "play2-scala-slick", 
         "setup_file": "setup_scala_slick", 
         "framework": "play2", 
         "language": "Scala", 
+        "flavor": "None",
         "orm": "Full", 
         "os": "Linux", 
         "database": "MySQL", 
@@ -110,9 +109,7 @@
         "db_url": "/db", 
         "query_url": "/queries?queries=", 
         "fortune_url": "/fortunes", 
-        "update_url": "/update?queries=",
-        "json_url": "/json",
-        "plaintext_url": "/plaintext"
+        "update_url": "/update?queries="
       }
     }
   ]

+ 4 - 16
frameworks/Scala/play2-scala/play2-scala-anorm/app/controllers/Application.scala

@@ -14,8 +14,6 @@ import scala.concurrent.{Future, ExecutionContext}
 class Application @Inject() (fortunesDAO: FortunesDAO, worldDAO: WorldDAO, dbOperation: DbOperation, val controllerComponents: ControllerComponents)(implicit ec: ExecutionContext)
   extends BaseController {
 
-  val defaultHeader = Http.HeaderNames.SERVER -> "Play Framework"
-
   def getRandomWorlds(n: Int): Future[Seq[World]] = dbOperation.asyncDbOp { implicit connection =>
     for (_ <- 1 to n) yield {
       worldDAO.findById(getNextRandom)
@@ -39,16 +37,6 @@ class Application @Inject() (fortunesDAO: FortunesDAO, worldDAO: WorldDAO, dbOpe
     ThreadLocalRandom.current().nextInt(TestDatabaseRows) + 1
   }
 
-  case class HelloWorld(message: String)
-
-  def getJsonMessage = Action {
-    val helloWorld = HelloWorld(message = "Hello, World!")
-    Ok(Json.toJson(helloWorld)(Json.writes[HelloWorld])).withHeaders(defaultHeader)
-  }
-
-  val plaintext = Action {
-    Ok("Hello, World!").withHeaders(defaultHeader).as("text/plain")
-  }
 
   // Common code between Scala database code
 
@@ -58,28 +46,28 @@ class Application @Inject() (fortunesDAO: FortunesDAO, worldDAO: WorldDAO, dbOpe
 
   def db = Action.async {
     getRandomWorlds(1).map { worlds =>
-      Ok(Json.toJson(worlds.head)).withHeaders(defaultHeader)
+      Ok(Json.toJson(worlds.head))
     }
   }
 
   def queries(countString: String) = Action.async {
     val n = parseCount(countString)
     getRandomWorlds(n).map { worlds =>
-      Ok(Json.toJson(worlds)).withHeaders(defaultHeader)
+      Ok(Json.toJson(worlds))
     }
   }
 
   def fortunes() = Action.async {
     getFortunes.map { dbFortunes =>
       val appendedFortunes =  Fortune(0, "Additional fortune added at request time.") :: dbFortunes.to[List]
-      Ok(views.html.fortune(appendedFortunes)).withHeaders(defaultHeader).as(HTML)
+      Ok(views.html.fortune(appendedFortunes))
     }
   }
 
   def update(queries: String) = Action.async {
     val n = parseCount(queries)
     updateWorlds(n).map { worlds =>
-      Ok(Json.toJson(worlds)).withHeaders(defaultHeader)
+      Ok(Json.toJson(worlds))
     }
   }
 

+ 1 - 2
frameworks/Scala/play2-scala/play2-scala-anorm/app/models/Fortune.scala

@@ -5,13 +5,12 @@ import javax.inject.{Inject, Singleton}
 import anorm._
 import anorm.SqlParser._
 import play.api.db.Database
-import play.db.NamedDatabase
 import scala.language.postfixOps
 
 case class Fortune(id: Long, message: String)
 
 @Singleton()
-class FortunesDAO @Inject()(@NamedDatabase("hello_world") protected val db: Database) {
+class FortunesDAO @Inject()(protected val db: Database) {
 
   private val simpleRowParser = {
     get[Long]("fortune.id") ~

+ 1 - 2
frameworks/Scala/play2-scala/play2-scala-anorm/app/models/World.scala

@@ -7,12 +7,11 @@ import anorm.SqlParser._
 import java.sql.Connection
 import play.api.db.Database
 import play.api.libs.json._
-import play.db.NamedDatabase
 
 case class World(id: Long, randomNumber: Long)
 
 @Singleton()
-class WorldDAO @Inject()(@NamedDatabase("hello_world") protected val db: Database) {
+class WorldDAO @Inject()(protected val db: Database) {
   /**
    * Parse a World from a ResultSet
    */

+ 8 - 23
frameworks/Scala/play2-scala/play2-scala-anorm/app/utils/DbOperation.scala

@@ -1,38 +1,21 @@
 package utils
 
+import akka.actor.ActorSystem
 import java.sql.Connection
 import java.util.concurrent._
 import javax.inject.{Singleton, Inject}
 import play.api.db.Database
+import play.api.libs.concurrent.CustomExecutionContext
 import play.api.Configuration
-import play.core.NamedThreadFactory
-import play.db.NamedDatabase
 import scala.concurrent._
 import scala.concurrent.Future
 
 @Singleton
-class DbOperation @Inject() (@NamedDatabase("hello_world") protected val db: Database,
-  configuration: Configuration) {
-
-  private val maxDbOperations = configuration.underlying.getInt("max-db-ops")
-
-  private val partitionCount = configuration.getOptional[Int]("db.hello_world.partitionCount").getOrElse(2)
-  private val maxConnections =
-    partitionCount * configuration.getOptional[Int]("db.hello_world.maxConnectionsPerPartition").getOrElse(5)
-  private val minConnections =
-    partitionCount * configuration.getOptional[Int]("db.hello_world.minConnectionsPerPartition").getOrElse(5)
-
-  private val tpe = new ThreadPoolExecutor(minConnections, maxConnections,
-    0L, TimeUnit.MILLISECONDS,
-    new LinkedBlockingQueue[Runnable](), // TODO: Could use ArrayBlockingQueue?
-    new NamedThreadFactory("dbEc"))
-  private val dbEc = ExecutionContext.fromExecutorService(tpe)
-
-  // Anorm code
+class DbOperation @Inject() (protected val db: Database,
+  configuration: Configuration, dbEc: DatabaseExecutionContext) {
 
   /**
-   * Run a DB operation in the DB context. Automatically
-   * provides a Session.
+   * Run a DB operation in the DB context.
    */
   def asyncDbOp[T](op: Connection => T): Future[T] = {
     // If the thread-pool queue used by the database grows too large then our server
@@ -40,10 +23,12 @@ class DbOperation @Inject() (@NamedDatabase("hello_world") protected val db: Dat
     // then we'll just slow everything down and it will fail anyway. Better to fail
     // quickly rather than slowly. Set the max size of our queue something above the
     // number of concurrent connections that we expect to be handling.
-    if (tpe.getQueue.size > maxDbOperations) sys.error(s"Aborted DB operation because queue is > $maxDbOperations")
     Future {
       db.withConnection { connection => op(connection) }
     }(dbEc)
   }
 
 }
+
+class DatabaseExecutionContext @Inject()(actorSystem: ActorSystem)
+ extends CustomExecutionContext(actorSystem, "database.dispatcher")

+ 3 - 2
frameworks/Scala/play2-scala/play2-scala-anorm/build.sbt

@@ -2,13 +2,14 @@ name := "play2-scala-anorm"
 
 version := "1.0-SNAPSHOT"
 
+lazy val root = (project in file(".")).enablePlugins(PlayScala)
+
 scalaVersion := "2.12.4"
 
-lazy val root = (project in file(".")).enablePlugins(PlayScala)
 
 libraryDependencies ++= Seq(
+  guice,
   jdbc,
   "com.typesafe.play" %% "anorm" % "2.5.3",
   "mysql" % "mysql-connector-java" % "5.1.44"
 )
-libraryDependencies += guice

+ 52 - 52
frameworks/Scala/play2-scala/play2-scala-anorm/conf/application.conf

@@ -1,69 +1,69 @@
-
 # This is the main configuration file for the application.
 # ~~~~~
 
 # 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.http.secret.key = "RItx1I:80?W@]8GAtPDuF8Ydd3mXM85p/<7og]Q;uBOdijQAauRDgu73B6`wQP59"
 
 # The application languages
 # ~~~~~
 play.i18n.langs = [ "en" ]
 
-# 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 `my.application.Router`,
-# you may need to define a router file `conf/my.application.routes`.
-# Default to Routes in the root package (and conf/routes)
-# play.http.router = my.application.Routes
-
-# 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.username=sa
-# db.default.password=""
-
-max-db-ops = 1024
-
-# You can expose this datasource via JNDI if needed (Useful for JPA)
-# db.default.jndiName=DefaultDS
-db.hello_world.driver= com.mysql.jdbc.Driver
-db.hello_world.url="jdbc:mysql://127.0.0.1:3306/hello_world?alwaysSendSetIsolation=false&avoidCheckOnDuplicateKeyUpdateInSQL=true&cacheCallableStmts=true&cachePrepStmts=true&cacheRSMetadata=true&cacheServerConfiguration=true&characterEncoding=UTF-8&dontTrackOpenResources=true&elideSetAutoCommits=true&jdbcCompliantTruncation=false&maintainTimeStats=false&prepStmtCacheSize=500&prepStmtCacheSqlLimit=2048&useUnbufferedInput=false&useReadAheadInput=false&useLocalSessionState=true&useServerPrepStmts&useSSL=false&rewriteBatchedStatements=true&traceProtocol=false&zeroDateTimeBehavior=convertToNull"
-db.hello_world.username=benchmarkdbuser
-db.hello_world.password=benchmarkdbpass
-db.hello_world.jndiName=DefaultDS
+# Disable default filters
+play.filters.enabled = [ ]
 
-db.hello_world.partitionCount=4
+play.server.akka.server-header = "Play2"
 
-# 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. Note that BoneCP will not create all these connections in
-# one go but rather start off with minConnectionsPerPartition and
-# gradually increase connections as required.
-db.hello_world.maxConnectionsPerPartition=64
+# 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
 
-# The number of initial connections, per partition.
-db.hello_world.minConnectionsPerPartition=64
+database.dispatcher {
+    executor = "thread-pool-executor"
+    throughput = 1
+    thread-pool-executor {
+        fixed-pool-size = ${fixedConnectionPool}
+    }
+}
 
-# Evolutions
+# Database configuration
 # ~~~~~
-# You can disable evolutions if needed
-play.evolutions.enabled=false
-
-# You can disable evolutions for a specific datasource if necessary
-# play.evolutions.db.default.enabled=false
-
-play.filters.enabled=[]
+# 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}
+        }
+    }
+}

+ 4 - 10
frameworks/Scala/play2-scala/play2-scala-anorm/conf/routes

@@ -2,13 +2,7 @@
 # This file defines all application routes (Higher priority routes first)
 # ~~~~
 
-# Home page
-GET     /json                           @controllers.Application.getJsonMessage
-GET     /db                             @controllers.Application.db
-GET     /queries                        @controllers.Application.queries(queries ?= "1")
-GET     /fortunes                       @controllers.Application.fortunes
-GET     /update                         @controllers.Application.update(queries ?= "1")
-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     /db                             controllers.Application.db
+GET     /queries                        controllers.Application.queries(queries: String ?= "1")
+GET     /fortunes                       controllers.Application.fortunes
+GET     /update                         controllers.Application.update(queries: String ?= "1")

+ 0 - 4
frameworks/Scala/play2-scala/play2-scala-anorm/project/plugins.sbt

@@ -1,5 +1 @@
-// Comment to get more information during initialization
-logLevel := Level.Warn
-
-// Use the Play sbt plugin for Play projects
 addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.6.7")

+ 2 - 5
frameworks/Scala/play2-scala/play2-scala-reactivemongo/app/AppLoader.scala

@@ -1,4 +1,3 @@
-import controllers.AssetsComponents
 import play.api.{controllers => _, _}
 import router.Routes
 import routing.Router
@@ -12,13 +11,11 @@ class AppLoader extends ApplicationLoader {
 }
 
 class AppComponents(context: Context)
-  extends ReactiveMongoApiFromContext(context)
-  with AssetsComponents {
+  extends ReactiveMongoApiFromContext(context) {
 
   override lazy val router: Router = new Routes(
     httpErrorHandler,
-    wire[controllers.Application],
-    wire[controllers.Assets]
+    wire[controllers.Application]
   )
 
   lazy val httpFilters = Seq.empty

+ 5 - 18
frameworks/Scala/play2-scala/play2-scala-reactivemongo/app/controllers/Application.scala

@@ -17,8 +17,6 @@ import play.modules.reactivemongo.json._
 class Application (val controllerComponents: ControllerComponents, reactiveMongoApi: ReactiveMongoApi)(implicit ec: ExecutionContext)
   extends BaseController {
 
-  val defaultHeader = Http.HeaderNames.SERVER -> "Play Framework"
-
   private def worldCollection: JSONCollection = reactiveMongoApi.db.collection[JSONCollection]("world")
   private def fortuneCollection: JSONCollection = reactiveMongoApi.db.collection[JSONCollection]("fortune")
   private val projection = Json.obj("_id" -> 0)
@@ -65,31 +63,20 @@ class Application (val controllerComponents: ControllerComponents, reactiveMongo
     ThreadLocalRandom.current().nextInt(TestDatabaseRows) + 1
   }
 
-  case class HelloWorld(message: String)
-
-  def getJsonMessage = Action {
-    val helloWorld = HelloWorld(message = "Hello, World!")
-    Ok(Json.toJson(helloWorld)(Json.writes[HelloWorld])).withHeaders(defaultHeader)
-  }
-
-  val plaintext = Action {
-    Ok("Hello, World!").withHeaders(defaultHeader).as("text/plain")
-  }
-
   // Semi-Common code between Scala database code
 
   protected val TestDatabaseRows = 10000
 
-  def doDb = Action.async {
+  def db = Action.async {
     getRandomWorld.map { worlds =>
-      Ok(Json.toJson(worlds.head)).withHeaders(defaultHeader)
+      Ok(Json.toJson(worlds.head))
     }
   }
 
   def queries(countString: String) = Action.async {
     val n = parseCount(countString)
     getRandomWorlds(n).map { worlds =>
-      Ok(Json.toJson(worlds)).withHeaders(defaultHeader)
+      Ok(Json.toJson(worlds))
     }
   }
 
@@ -103,14 +90,14 @@ class Application (val controllerComponents: ControllerComponents, reactiveMongo
 
       val sorted = appendedFortunes.sortBy(byMessage(_))
 
-      Ok(views.html.fortune(sorted)).withHeaders(defaultHeader).as(HTML)
+      Ok(views.html.fortune(sorted))
     }
   }
 
   def update(queries: String) = Action.async {
     val n = parseCount(queries)
     updateWorlds(n).map { worlds =>
-      Ok(Json.toJson(worlds)).withHeaders(defaultHeader)
+      Ok(Json.toJson(worlds))
     }
   }
 

+ 2 - 4
frameworks/Scala/play2-scala/play2-scala-reactivemongo/build.sbt

@@ -2,11 +2,9 @@ name := "play2-scala-reactivemongo"
 
 version := "1.0-SNAPSHOT"
 
-scalaVersion := "2.12.4"
+lazy val root = (project in file(".")).enablePlugins(PlayScala)
 
-lazy val root =
-  (project in file(".")).
-  enablePlugins(PlayScala)
+scalaVersion := "2.12.4"
 
 libraryDependencies ++= Seq(
   "org.reactivemongo" %% "play2-reactivemongo" % "0.12.7-play26",

+ 9 - 36
frameworks/Scala/play2-scala/play2-scala-reactivemongo/conf/application.conf

@@ -4,50 +4,23 @@
 # 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.http.secret.key = "RItx1I:80?W@]8GAtPDuF8Ydd3mXM85p/<7og]Q;uBOdijQAauRDgu73B6`wQP59"
 
 # The application languages
 # ~~~~~
 play.i18n.langs = [ "en" ]
 
-# 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 `my.application.Router`,
-# you may need to define a router file `conf/my.application.routes`.
-# Default to Routes in the root package (and conf/routes)
-# play.http.router = my.application.Routes
-
-# 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.username=sa
-# db.default.password=""
+# Disable default filters
+play.filters.enabled = [ ]
 
-# Evolutions
-# ~~~~~
-# You can disable evolutions if needed
-play.evolutions.enabled=false
+play.server.akka.server-header = "Play2"
 
-# You can disable evolutions for a specific datasource if necessary
-# play.evolutions.db.default.enabled=false
+play.application.loader=AppLoader
 
 play.modules.enabled += "play.modules.reactivemongo.ReactiveMongoModule"
 
-mongodb.servers = ["TFB-database:27017"]
-mongodb.db = "hello_world"
-mongodb.uri = "mongodb://TFB-database:27017/hello_world"
-
-play.filters.enabled=[]
-play.application.loader=AppLoader
+mongodb {
+  servers = ["TFB-database:27017"]
+  db = "hello_world"
+  uri = "mongodb://TFB-database:27017/hello_world"
+}

+ 2 - 8
frameworks/Scala/play2-scala/play2-scala-reactivemongo/conf/routes

@@ -2,13 +2,7 @@
 # This file defines all application routes (Higher priority routes first)
 # ~~~~
 
-# Home page
-GET     /json                           controllers.Application.getJsonMessage
-GET     /db                             controllers.Application.doDb
+GET     /db                             controllers.Application.db
 GET     /queries                        controllers.Application.queries(queries: String ?= "1")
 GET     /fortunes                       controllers.Application.fortunes
-GET     /update                         controllers.Application.update(queries ?= "1")
-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     /update                         controllers.Application.update(queries: String ?= "1")

+ 0 - 1
frameworks/Scala/play2-scala/play2-scala-reactivemongo/project/plugins.sbt

@@ -1,2 +1 @@
-// Use the Play sbt plugin for Play projects
 addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.6.7")

+ 4 - 17
frameworks/Scala/play2-scala/play2-scala-slick/app/controllers/Application.scala

@@ -12,8 +12,6 @@ import scala.concurrent.{Future, ExecutionContext}
 class Application @Inject() (fortunesDAO: FortunesDAO, worldDAO: WorldDAO, val controllerComponents: ControllerComponents)(implicit ec: ExecutionContext)
   extends BaseController {
 
-  val defaultHeader = Http.HeaderNames.SERVER -> "Play Framework"
-
   def getRandomWorlds(n: Int): Future[Seq[World]] = {
     val worlds: Seq[Future[World]] = for (_ <- 1 to n) yield {
       worldDAO.findById(getNextRandom)
@@ -39,17 +37,6 @@ class Application @Inject() (fortunesDAO: FortunesDAO, worldDAO: WorldDAO, val c
     ThreadLocalRandom.current().nextInt(TestDatabaseRows) + 1
   }
 
-  case class HelloWorld(message: String)
-
-  def getJsonMessage = Action {
-    val helloWorld = HelloWorld(message = "Hello, World!")
-    Ok(Json.toJson(helloWorld)(Json.writes[HelloWorld])).withHeaders(defaultHeader)
-  }
-
-  val plaintext = Action {
-    Ok("Hello, World!").withHeaders(defaultHeader).as("text/plain")
-  }
-
   // Common code between Scala database code
 
   protected val TestDatabaseRows = 10000
@@ -58,28 +45,28 @@ class Application @Inject() (fortunesDAO: FortunesDAO, worldDAO: WorldDAO, val c
 
   def db = Action.async {
     getRandomWorlds(1).map { worlds =>
-      Ok(Json.toJson(worlds.head)).withHeaders(defaultHeader)
+      Ok(Json.toJson(worlds.head))
     }
   }
 
   def queries(countString: String) = Action.async {
     val n = parseCount(countString)
     getRandomWorlds(n).map { worlds =>
-      Ok(Json.toJson(worlds)).withHeaders(defaultHeader)
+      Ok(Json.toJson(worlds))
     }
   }
 
   def fortunes() = Action.async {
     getFortunes.map { dbFortunes =>
       val appendedFortunes =  Fortune(0, "Additional fortune added at request time.") :: dbFortunes.to[List]
-      Ok(views.html.fortune(appendedFortunes)).withHeaders(defaultHeader).as(HTML)
+      Ok(views.html.fortune(appendedFortunes))
     }
   }
 
   def update(queries: String) = Action.async {
     val n = parseCount(queries)
     updateWorlds(n).map { worlds =>
-      Ok(Json.toJson(worlds)).withHeaders(defaultHeader)
+      Ok(Json.toJson(worlds))
     }
   }
 

+ 1 - 2
frameworks/Scala/play2-scala/play2-scala-slick/app/models/Fortune.scala

@@ -3,7 +3,6 @@ package models
 import javax.inject.{Inject, Singleton}
 
 import play.api.db.slick.{HasDatabaseConfigProvider, DatabaseConfigProvider}
-import play.db.NamedDatabase
 import slick.jdbc.JdbcProfile
 
 import scala.concurrent.Future
@@ -11,7 +10,7 @@ import scala.concurrent.Future
 case class Fortune(id: Long, message: String)
 
 @Singleton()
-class FortunesDAO @Inject()(@NamedDatabase("hello_world") protected val dbConfigProvider: DatabaseConfigProvider) extends HasDatabaseConfigProvider[JdbcProfile] {
+class FortunesDAO @Inject()(protected val dbConfigProvider: DatabaseConfigProvider) extends HasDatabaseConfigProvider[JdbcProfile] {
 
   import profile.api._
 

+ 1 - 2
frameworks/Scala/play2-scala/play2-scala-slick/app/models/World.scala

@@ -7,12 +7,11 @@ import scala.concurrent.Future
 import javax.inject.{Singleton, Inject}
 import play.api.db.slick.DatabaseConfigProvider
 import play.api.db.slick.HasDatabaseConfigProvider
-import play.db.NamedDatabase
 import slick.jdbc.JdbcProfile
 import scala.concurrent.ExecutionContext
 
 @Singleton()
-class WorldDAO @Inject()(@NamedDatabase("hello_world") protected val dbConfigProvider: DatabaseConfigProvider) (implicit ec: ExecutionContext)
+class WorldDAO @Inject()(protected val dbConfigProvider: DatabaseConfigProvider) (implicit ec: ExecutionContext)
   extends HasDatabaseConfigProvider[JdbcProfile] {
 
   import profile.api._

+ 3 - 3
frameworks/Scala/play2-scala/play2-scala-slick/build.sbt

@@ -2,13 +2,13 @@ name := "play2-scala-slick"
 
 version := "1.0-SNAPSHOT"
 
-scalaVersion := "2.12.4"
-
 lazy val root = (project in file(".")).enablePlugins(PlayScala)
 
+scalaVersion := "2.12.4"
+
 libraryDependencies ++= Seq(
+  guice,
   "com.typesafe.play" %% "play-slick" % "3.0.2",
   "mysql" % "mysql-connector-java" % "5.1.44",
   filters
 )
-libraryDependencies += guice

+ 44 - 44
frameworks/Scala/play2-scala/play2-scala-slick/conf/application.conf

@@ -1,60 +1,60 @@
 # This is the main configuration file for the application.
 # ~~~~~
 
-# The max size of the queue for running db operations
-#max-db-ops = 1024
-
 # 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
 # ~~~~~
-play.i18n.langs=["en"]
-
-# Global object class
-# ~~~~~
-# Define the Global object class for this application.
-# Default to Global in the root package.
-# global=Global
+play.i18n.langs = [ "en" ]
 
-# Database configuration
-# ~~~~~ 
+# Disable default filters
+play.filters.enabled = [ ]
 
-slick.dbs.hello_world.profile="slick.jdbc.MySQLProfile$"
-slick.dbs.hello_world.db.driver="com.mysql.jdbc.Driver"
-slick.dbs.hello_world.db.url="jdbc:mysql://127.0.0.1:3306/hello_world?alwaysSendSetIsolation=false&avoidCheckOnDuplicateKeyUpdateInSQL=true&cacheCallableStmts=true&cachePrepStmts=true&cacheRSMetadata=true&cacheServerConfiguration=true&characterEncoding=UTF-8&dontTrackOpenResources=true&elideSetAutoCommits=true&jdbcCompliantTruncation=false&maintainTimeStats=false&prepStmtCacheSize=500&prepStmtCacheSqlLimit=2048&useUnbufferedInput=false&useReadAheadInput=false&useLocalSessionState=true&useServerPrepStmts&useSSL=false&rewriteBatchedStatements=true&traceProtocol=false&zeroDateTimeBehavior=convertToNull"
-slick.dbs.hello_world.db.user="benchmarkdbuser"
-slick.dbs.hello_world.db.password="benchmarkdbpass"
-slick.dbs.hello_world.db.connectionPool = HikariCP
-slick.dbs.hello_world.db.keepAliveConnection = true
-#slick.dbs.hello_world.db.connectionTestQuery="select 1"
+play.server.akka.server-header = "Play2"
 
-# Evolutions
+# Database configuration
 # ~~~~~
-# You can disable evolutions if needed
-evolutionplugin=disabled
-
-play {
-  akka {
-    event-handlers = ["akka.event.slf4j.Slf4jEventHandler"]
-    loglevel = WARNING
-    actor {
-      default-dispatcher = {
-        fork-join-executor {
-          parallelism-factor = 1.0
-          parallelism-max = 50
-        }
-      }
-      application = {
-        fork-join-executor {
-          parallelism-max = 300
-        }
-      }
+slick.dbs.default {
+  profile="slick.jdbc.MySQLProfile$"
+  db {
+    connectionPool=HikariCP
+    driver="com.mysql.jdbc.Driver"
+    url="jdbc:mysql://TFB-database:3306/hello_world"
+    user="benchmarkdbuser"
+    password="benchmarkdbpass"
+
+    # Number of threads
+    # 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
+    numThreads=17
+    #queueSize=100
+
+    properties {
+      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
     }
   }
 }
-
-play.filters.enabled=[]

+ 4 - 10
frameworks/Scala/play2-scala/play2-scala-slick/conf/routes

@@ -2,13 +2,7 @@
 # This file defines all application routes (Higher priority routes first)
 # ~~~~
 
-# Home page
-GET     /json                           @controllers.Application.getJsonMessage
-GET     /db                             @controllers.Application.db
-GET     /queries                        @controllers.Application.queries(queries ?= "1")
-GET     /fortunes                       @controllers.Application.fortunes
-GET     /update                         @controllers.Application.update(queries ?= "1")
-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     /db                             controllers.Application.db
+GET     /queries                        controllers.Application.queries(queries: String ?= "1")
+GET     /fortunes                       controllers.Application.fortunes
+GET     /update                         controllers.Application.update(queries: String ?= "1")

+ 0 - 4
frameworks/Scala/play2-scala/play2-scala-slick/project/plugins.sbt

@@ -1,5 +1 @@
-// Comment to get more information during initialization
-logLevel := Level.Warn
-
-// Use the Play sbt plugin for Play projects
 addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.6.7")

+ 2 - 4
frameworks/Scala/play2-scala/play2-scala/app/controllers/Application.scala

@@ -12,14 +12,12 @@ extends AbstractController(cc) {
 
   implicit final val helloWorldWrites = Json.writes[HelloWorld]
 
-  val defaultHeader = Http.HeaderNames.SERVER -> "Play Framework"
-
   def getJsonMessage = Action {
-    Ok( Json.toJson(HelloWorld()) ).withHeaders(defaultHeader)
+    Ok( Json.toJson(HelloWorld()) )
   }
 
   val plaintext = Action {
-    Ok("Hello, World!").withHeaders(defaultHeader).as("text/plain")
+    Ok("Hello, World!").as(play.api.http.MimeTypes.TEXT)
   }
 }
 

+ 6 - 6
frameworks/Scala/play2-scala/play2-scala/build.sbt

@@ -2,11 +2,11 @@ name := "play2-scala"
 
 version := "1.0-SNAPSHOT"
 
-scalaVersion := "2.12.4"
+lazy val root = (project in file(".")).enablePlugins(PlayScala)
 
-val root =
-  (project in file(".")).
-  enablePlugins(PlayScala)
+scalaVersion := "2.12.4"
 
-libraryDependencies += "com.typesafe.play" %% "play-json" % "2.6.6"
-libraryDependencies += guice
+libraryDependencies ++= Seq(
+  guice,
+  "com.typesafe.play" %% "play-json" % "2.6.7"
+)

+ 3 - 52
frameworks/Scala/play2-scala/play2-scala/conf/application.conf

@@ -4,62 +4,13 @@
 # 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.http.secret.key = "RItx1I:80?W@]8GAtPDuF8Ydd3mXM85p/<7og]Q;uBOdijQAauRDgu73B6`wQP59"
 
 # The application languages
 # ~~~~~
 play.i18n.langs = [ "en" ]
 
-# 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 `my.application.Router`,
-# you may need to define a router file `conf/my.application.routes`.
-# Default to Routes in the root package (and conf/routes)
-# play.http.router = my.application.Routes
-
-# 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.username=sa
-# db.default.password=""
-
-# Evolutions
-# ~~~~~
-# You can disable evolutions if needed
-play.evolutions.enabled=false
-
-# You can disable evolutions for a specific datasource if necessary
-# play.evolutions.db.default.enabled=false
-
-play.server {
-  netty {
-    transport = "native"
-
-    option {
-      SO_BACKLOG = 128
-
-      child {
-        SO_KEEPALIVE = true
-        TCP_NODELAY = true
-      }
-    }
-  }
-}
-
-akka {
-  log-dead-letters = off
-}
+# Disable default filters
+play.filters.enabled = [ ]
 
-play.filters.enabled=[]
+play.server.akka.server-header = "Play2"

+ 4 - 0
frameworks/Scala/play2-scala/play2-scala/conf/routes

@@ -1,2 +1,6 @@
+# Routes
+# This file defines all application routes (Higher priority routes first)
+# ~~~~
+
 GET     /json       controllers.Application.getJsonMessage
 GET     /plaintext  controllers.Application.plaintext

+ 0 - 4
frameworks/Scala/play2-scala/play2-scala/project/plugins.sbt

@@ -1,5 +1 @@
-// Comment to get more information during initialization
-logLevel := Level.Warn
-
-// Use the Play sbt plugin for Play projects
 addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.6.7")