Browse Source

Merge branch 'master' of TechEmpower/FrameworkBenchmarks into toolset-fix-448

Conflicts:
	frameworks/Java/play-java/.gitignore
	frameworks/Java/play-java/README.md
	frameworks/Java/play-java/app/controllers/Application.java
	frameworks/Java/play-java/app/models/World.java
	frameworks/Java/play-java/app/utils/Predicate.java
	frameworks/Java/play-java/app/utils/Predicated.java
	frameworks/Java/play-java/app/utils/PredicatedAction.java
	frameworks/Java/play-java/benchmark_config
	frameworks/Java/play-java/build.sbt
	frameworks/Java/play-java/conf/application.conf
	frameworks/Java/play-java/conf/routes
	frameworks/Java/play-java/install.sh
	frameworks/Java/play-java/setup.py
	frameworks/Java/play-java/source_code
	frameworks/Scala/play-activate-mysql/project/build.properties
	frameworks/Scala/play-activate-mysql/project/plugins.sbt
	frameworks/Scala/play-scala/.gitignore
	frameworks/Scala/play-scala/README.md
	frameworks/Scala/play-scala/app/controllers/Application.scala
	frameworks/Scala/play-scala/app/models/Fortune.scala
	frameworks/Scala/play-scala/app/models/World.scala
	frameworks/Scala/play-scala/app/utils/PredicatedAction.scala
	frameworks/Scala/play-scala/app/views/fortune.scala.html
	frameworks/Scala/play-scala/app/views/main.scala.html
	frameworks/Scala/play-scala/benchmark_config
	frameworks/Scala/play-scala/build.sbt
	frameworks/Scala/play-scala/conf/application.conf
	frameworks/Scala/play-scala/conf/routes
	frameworks/Scala/play-scala/install.sh
	frameworks/Scala/play-scala/project/build.properties
	frameworks/Scala/play-scala/project/plugins.sbt
	frameworks/Scala/play-scala/setup.py
	frameworks/Scala/play-scala/source_code
	play-java/.gitignore
	play-java/README.md
	play-java/app/models/World.java
	play-java/app/utils/Predicate.java
	play-java/app/utils/Predicated.java
	play-java/app/utils/PredicatedAction.java
	play-java/build.sbt
	play-java/conf/application.conf
	play-java/conf/routes
	play-java/project/build.properties
	play-java/project/plugins.sbt
	play-java/source_code
	play-scala/.gitignore
	play-scala/README.md
	play-scala/app/models/Fortune.scala
	play-scala/app/models/World.scala
	play-scala/app/utils/PredicatedAction.scala
	play-scala/app/views/fortune.scala.html
	play-scala/app/views/main.scala.html
	play-scala/build.sbt
	play-scala/conf/application.conf
	play-scala/conf/routes
	play-scala/project/build.properties
	play-scala/project/plugins.sbt
	play-scala/source_code
	play2/play2-java-ebean/.gitignore
	play2/play2-java-ebean/README.md
	play2/play2-java-ebean/app/models/World.java
	play2/play2-java-ebean/app/utils/Predicate.java
	play2/play2-java-ebean/app/utils/Predicated.java
	play2/play2-java-ebean/app/utils/PredicatedAction.java
	play2/play2-java-ebean/build.sbt
	play2/play2-java-ebean/conf/application.conf
	play2/play2-java-ebean/project/build.properties
	play2/play2-java-ebean/project/plugins.sbt
	play2/play2-java-ebean/source_code
	play2/play2-java/conf/routes
	play2/play2-scala-anorm/.gitignore
	play2/play2-scala-anorm/README.md
	play2/play2-scala-anorm/app/models/Fortune.scala
	play2/play2-scala-anorm/app/models/World.scala
	play2/play2-scala-anorm/app/utils/PredicatedAction.scala
	play2/play2-scala-anorm/app/views/fortune.scala.html
	play2/play2-scala-anorm/app/views/main.scala.html
	play2/play2-scala-anorm/build.sbt
	play2/play2-scala-anorm/conf/application.conf
	play2/play2-scala-anorm/conf/routes
	play2/play2-scala-anorm/project/build.properties
	play2/play2-scala-anorm/project/plugins.sbt
	play2/play2-scala-anorm/source_code
Hamilton Turner 11 years ago
parent
commit
d39c22b16c
100 changed files with 2301 additions and 3 deletions
  1. 2 2
      .travis.yml
  2. 2 1
      config/benchmark_profile
  3. 5 0
      frameworks/Java/play2-java/README.md
  4. 0 0
      frameworks/Java/play2-java/__init__.py
  5. 1 0
      frameworks/Java/play2-java/bash_profile.sh
  6. 104 0
      frameworks/Java/play2-java/benchmark_config
  7. 72 0
      frameworks/Java/play2-java/generate_config.py
  8. 3 0
      frameworks/Java/play2-java/install.sh
  9. 30 0
      frameworks/Java/play2-java/play2-java-ebean/.gitignore
  10. 20 0
      frameworks/Java/play2-java/play2-java-ebean/README.md
  11. 97 0
      frameworks/Java/play2-java/play2-java-ebean/app/controllers/Application.java
  12. 20 0
      frameworks/Java/play2-java/play2-java-ebean/app/models/World.java
  13. 8 0
      frameworks/Java/play2-java/play2-java-ebean/app/utils/Predicate.java
  14. 26 0
      frameworks/Java/play2-java/play2-java-ebean/app/utils/Predicated.java
  15. 23 0
      frameworks/Java/play2-java/play2-java-ebean/app/utils/PredicatedAction.java
  16. 13 0
      frameworks/Java/play2-java/play2-java-ebean/build.sbt
  17. 74 0
      frameworks/Java/play2-java/play2-java-ebean/conf/application.conf
  18. 10 0
      frameworks/Java/play2-java/play2-java-ebean/conf/routes
  19. 1 0
      frameworks/Java/play2-java/play2-java-ebean/project/build.properties
  20. 8 0
      frameworks/Java/play2-java/play2-java-ebean/project/plugins.sbt
  21. 9 0
      frameworks/Java/play2-java/play2-java-ebean/source_code
  22. 30 0
      frameworks/Java/play2-java/play2-java/.gitignore
  23. 18 0
      frameworks/Java/play2-java/play2-java/README.md
  24. 19 0
      frameworks/Java/play2-java/play2-java/app/controllers/Application.java
  25. 5 0
      frameworks/Java/play2-java/play2-java/build.sbt
  26. 26 0
      frameworks/Java/play2-java/play2-java/conf/application.conf
  27. 9 0
      frameworks/Java/play2-java/play2-java/conf/routes
  28. 1 0
      frameworks/Java/play2-java/play2-java/project/build.properties
  29. 8 0
      frameworks/Java/play2-java/play2-java/project/plugins.sbt
  30. 9 0
      frameworks/Java/play2-java/play2-java/source_code
  31. 33 0
      frameworks/Java/play2-java/play2-scala-anorm/.gitignore
  32. 20 0
      frameworks/Java/play2-java/play2-scala-anorm/README.md
  33. 106 0
      frameworks/Java/play2-java/play2-scala-anorm/app/controllers/Application.scala
  34. 25 0
      frameworks/Java/play2-java/play2-scala-anorm/app/models/Fortune.scala
  35. 55 0
      frameworks/Java/play2-java/play2-scala-anorm/app/models/World.scala
  36. 20 0
      frameworks/Java/play2-java/play2-scala-anorm/app/utils/PredicatedAction.scala
  37. 18 0
      frameworks/Java/play2-java/play2-scala-anorm/app/views/fortune.scala.html
  38. 12 0
      frameworks/Java/play2-java/play2-scala-anorm/app/views/main.scala.html
  39. 9 0
      frameworks/Java/play2-java/play2-scala-anorm/build.sbt
  40. 66 0
      frameworks/Java/play2-java/play2-scala-anorm/conf/application.conf
  41. 12 0
      frameworks/Java/play2-java/play2-scala-anorm/conf/routes
  42. 1 0
      frameworks/Java/play2-java/play2-scala-anorm/project/build.properties
  43. 8 0
      frameworks/Java/play2-java/play2-scala-anorm/project/plugins.sbt
  44. 11 0
      frameworks/Java/play2-java/play2-scala-anorm/source_code
  45. 33 0
      frameworks/Java/play2-java/play2-scala/.gitignore
  46. 18 0
      frameworks/Java/play2-java/play2-scala/README.md
  47. 12 0
      frameworks/Java/play2-java/play2-scala/app/controllers/Application.scala
  48. 5 0
      frameworks/Java/play2-java/play2-scala/build.sbt
  49. 31 0
      frameworks/Java/play2-java/play2-scala/conf/application.conf
  50. 9 0
      frameworks/Java/play2-java/play2-scala/conf/routes
  51. 1 0
      frameworks/Java/play2-java/play2-scala/project/build.properties
  52. 8 0
      frameworks/Java/play2-java/play2-scala/project/plugins.sbt
  53. 11 0
      frameworks/Java/play2-java/play2-scala/source_code
  54. 55 0
      frameworks/Java/play2-java/setup_common.py
  55. 6 0
      frameworks/Java/play2-java/setup_java.py
  56. 6 0
      frameworks/Java/play2-java/setup_java_ebean.py
  57. 6 0
      frameworks/Java/play2-java/setup_scala.py
  58. 6 0
      frameworks/Java/play2-java/setup_scala_anorm.py
  59. 5 0
      frameworks/Scala/play2-scala/README.md
  60. 0 0
      frameworks/Scala/play2-scala/__init__.py
  61. 1 0
      frameworks/Scala/play2-scala/bash_profile.sh
  62. 104 0
      frameworks/Scala/play2-scala/benchmark_config
  63. 72 0
      frameworks/Scala/play2-scala/generate_config.py
  64. 3 0
      frameworks/Scala/play2-scala/install.sh
  65. 30 0
      frameworks/Scala/play2-scala/play2-java-ebean/.gitignore
  66. 20 0
      frameworks/Scala/play2-scala/play2-java-ebean/README.md
  67. 97 0
      frameworks/Scala/play2-scala/play2-java-ebean/app/controllers/Application.java
  68. 20 0
      frameworks/Scala/play2-scala/play2-java-ebean/app/models/World.java
  69. 8 0
      frameworks/Scala/play2-scala/play2-java-ebean/app/utils/Predicate.java
  70. 26 0
      frameworks/Scala/play2-scala/play2-java-ebean/app/utils/Predicated.java
  71. 23 0
      frameworks/Scala/play2-scala/play2-java-ebean/app/utils/PredicatedAction.java
  72. 13 0
      frameworks/Scala/play2-scala/play2-java-ebean/build.sbt
  73. 74 0
      frameworks/Scala/play2-scala/play2-java-ebean/conf/application.conf
  74. 10 0
      frameworks/Scala/play2-scala/play2-java-ebean/conf/routes
  75. 1 0
      frameworks/Scala/play2-scala/play2-java-ebean/project/build.properties
  76. 8 0
      frameworks/Scala/play2-scala/play2-java-ebean/project/plugins.sbt
  77. 9 0
      frameworks/Scala/play2-scala/play2-java-ebean/source_code
  78. 30 0
      frameworks/Scala/play2-scala/play2-java/.gitignore
  79. 18 0
      frameworks/Scala/play2-scala/play2-java/README.md
  80. 19 0
      frameworks/Scala/play2-scala/play2-java/app/controllers/Application.java
  81. 5 0
      frameworks/Scala/play2-scala/play2-java/build.sbt
  82. 26 0
      frameworks/Scala/play2-scala/play2-java/conf/application.conf
  83. 9 0
      frameworks/Scala/play2-scala/play2-java/conf/routes
  84. 1 0
      frameworks/Scala/play2-scala/play2-java/project/build.properties
  85. 8 0
      frameworks/Scala/play2-scala/play2-java/project/plugins.sbt
  86. 9 0
      frameworks/Scala/play2-scala/play2-java/source_code
  87. 33 0
      frameworks/Scala/play2-scala/play2-scala-anorm/.gitignore
  88. 20 0
      frameworks/Scala/play2-scala/play2-scala-anorm/README.md
  89. 106 0
      frameworks/Scala/play2-scala/play2-scala-anorm/app/controllers/Application.scala
  90. 25 0
      frameworks/Scala/play2-scala/play2-scala-anorm/app/models/Fortune.scala
  91. 55 0
      frameworks/Scala/play2-scala/play2-scala-anorm/app/models/World.scala
  92. 20 0
      frameworks/Scala/play2-scala/play2-scala-anorm/app/utils/PredicatedAction.scala
  93. 18 0
      frameworks/Scala/play2-scala/play2-scala-anorm/app/views/fortune.scala.html
  94. 12 0
      frameworks/Scala/play2-scala/play2-scala-anorm/app/views/main.scala.html
  95. 9 0
      frameworks/Scala/play2-scala/play2-scala-anorm/build.sbt
  96. 66 0
      frameworks/Scala/play2-scala/play2-scala-anorm/conf/application.conf
  97. 12 0
      frameworks/Scala/play2-scala/play2-scala-anorm/conf/routes
  98. 1 0
      frameworks/Scala/play2-scala/play2-scala-anorm/project/build.properties
  99. 8 0
      frameworks/Scala/play2-scala/play2-scala-anorm/project/plugins.sbt
  100. 11 0
      frameworks/Scala/play2-scala/play2-scala-anorm/source_code

+ 2 - 2
.travis.yml

@@ -97,10 +97,10 @@ env:
     - TESTDIR=plain
     - TESTDIR=play1
     - TESTDIR=play1siena
+    - TESTDIR=play2-java
+    - TESTDIR=play2-scala
     - TESTDIR=play-activate-mysql
-    - TESTDIR=play-java
     - TESTDIR=play-java-jpa
-    - TESTDIR=play-scala
     - TESTDIR=play-scala-mongodb
     - TESTDIR=play-slick
     - TESTDIR=pyramid

+ 2 - 1
config/benchmark_profile

@@ -21,6 +21,7 @@ export NODE_HOME=${IROOT}/node-v0.10.8-linux-x64
 export PLAY_HOME=${IROOT}/play-2.2.0
 export PLAY1_HOME=${IROOT}/play-1.2.5
 export MAVEN_HOME=${IROOT}/apache-maven-3.0.5
+export SBT_HOME=${IROOT}/sbt
 export PERL_HOME=${IROOT}/perl-5.18
 export DART_HOME=${IROOT}/dart-sdk
 export RACKET_HOME=${IROOT}/racket-5.3.6
@@ -28,7 +29,7 @@ export NIMROD_HOME=${IROOT}/nimrod
 export NGINX_HOME=/usr/local/nginx
 export ELIXIR_HOME=${IROOT}/elixir-0.13.3
 
-export PATH="$JAVA_HOME/bin:$GRAILS_HOME/bin:$PLAY_HOME:$PLAY1_HOME:$VERTX_HOME/bin:$GOROOT/bin:$NODE_HOME/bin:$HOME/FrameworkBenchmarks/installs/bin:$MAVEN_HOME/bin:$PERL_HOME/bin:$DART_HOME/bin:$RACKET_HOME/bin:$NIMROD_HOME/bin:$NGINX_HOME/sbin:$ELIXIR_HOME/bin:$PATH"
+export PATH="$JAVA_HOME/bin:$GRAILS_HOME/bin:$PLAY_HOME:$PLAY1_HOME:$VERTX_HOME/bin:$GOROOT/bin:$NODE_HOME/bin:$HOME/FrameworkBenchmarks/installs/bin:$MAVEN_HOME/bin:$SBT_HOME/bin:$PERL_HOME/bin:$DART_HOME/bin:$RACKET_HOME/bin:$NIMROD_HOME/bin:$NGINX_HOME/sbin:$ELIXIR_HOME/bin:$PATH"
 
 export LD_LIBRARY_PATH='$LD_LIBRARY_PATH:/usr/local/apr/lib'
 

+ 5 - 0
frameworks/Java/play2-java/README.md

@@ -0,0 +1,5 @@
+# play2 framework tests
+
+1. Add new test applications in subdirectories named either `play2-language` or `play2-language-orm`.
+2. Edit `generate_config.py` and add configuration for the new test applications.
+3. Run `python generate_config.py` to generate a new `benchmark_config` file and to generate a `setup_play2_*.py` file for your test application.

+ 0 - 0
frameworks/Java/play2-java/__init__.py


+ 1 - 0
frameworks/Java/play2-java/bash_profile.sh

@@ -0,0 +1 @@
+# Intentionally blank

+ 104 - 0
frameworks/Java/play2-java/benchmark_config

@@ -0,0 +1,104 @@
+{
+  "framework": "play2", 
+  "tests": [
+    {
+      "java": {
+        "display_name": "play2-java", 
+        "setup_file": "setup_java", 
+        "framework": "play2", 
+        "language": "Java", 
+        "orm": "Raw", 
+        "os": "Linux", 
+        "database": "None", 
+        "approach": "Realistic", 
+        "classification": "Fullstack", 
+        "platform": "Netty", 
+        "webserver": "None", 
+        "database_os": "Linux", 
+        "notes": "", 
+        "versus": "netty", 
+        "port": "9000", 
+        "json_url": "/json"
+      }, 
+      "scala": {
+        "display_name": "play2-scala", 
+        "setup_file": "setup_scala", 
+        "framework": "play2", 
+        "language": "Scala", 
+        "orm": "Raw", 
+        "os": "Linux", 
+        "database": "None", 
+        "approach": "Realistic", 
+        "classification": "Fullstack", 
+        "platform": "Netty", 
+        "webserver": "None", 
+        "database_os": "Linux", 
+        "notes": "", 
+        "versus": "netty", 
+        "port": "9000", 
+        "json_url": "/json"
+      }, 
+      "java-ebean": {
+        "display_name": "play2-java-ebean", 
+        "setup_file": "setup_java_ebean", 
+        "framework": "play2", 
+        "language": "Java", 
+        "orm": "Ebean", 
+        "os": "Linux", 
+        "database": "MySQL", 
+        "approach": "Realistic", 
+        "classification": "Fullstack", 
+        "platform": "Netty", 
+        "webserver": "None", 
+        "database_os": "Linux", 
+        "notes": "", 
+        "versus": "netty", 
+        "port": "9000", 
+        "db_url": "/db", 
+        "query_url": "/queries?queries="
+      }, 
+      "scala-anorm-linux": {
+        "display_name": "play2-scala-anorm-linux", 
+        "setup_file": "setup_scala_anorm", 
+        "framework": "play2", 
+        "language": "Scala", 
+        "orm": "Anorm", 
+        "os": "Linux", 
+        "database": "MySQL", 
+        "approach": "Realistic", 
+        "classification": "Fullstack", 
+        "platform": "Netty", 
+        "webserver": "None", 
+        "database_os": "Linux", 
+        "notes": "", 
+        "versus": "netty", 
+        "port": "9000", 
+        "db_url": "/db", 
+        "query_url": "/queries?queries=", 
+        "fortune_url": "/fortunes", 
+        "update_url": "/update?queries="
+      }, 
+      "scala-anorm-windows": {
+        "display_name": "play2-scala-anorm-windows", 
+        "setup_file": "setup_scala_anorm", 
+        "framework": "play2", 
+        "language": "Scala", 
+        "orm": "Anorm", 
+        "os": "Windows", 
+        "database": "MySQL", 
+        "approach": "Realistic", 
+        "classification": "Fullstack", 
+        "platform": "Netty", 
+        "webserver": "None", 
+        "database_os": "Linux", 
+        "notes": "", 
+        "versus": "netty", 
+        "port": "9000", 
+        "db_url": "/db", 
+        "query_url": "/queries?queries=", 
+        "fortune_url": "/fortunes", 
+        "update_url": "/update?queries="
+      }
+    }
+  ]
+}

+ 72 - 0
frameworks/Java/play2-java/generate_config.py

@@ -0,0 +1,72 @@
+#!/usr/bin/env python
+
+import collections, json, textwrap
+
+# This script generates the benchmark_config and setup_*.py files.
+# To add new tests, modify the `configurations` and `test_urls` tables.
+
+# Each line corresponds to a test application.
+# Format is: (language, orm, (os, ...), (test, ...))
+# See the dir_name logic below to see the directory name for each test application.
+configurations = [
+  ('Java',  None,    ['Linux'],            ['json']),
+  ('Scala', None,    ['Linux'],            ['json']),
+  ('Java',  'Ebean', ['Linux'],            ['db', 'query']),
+  ('Scala', 'Anorm', ['Linux', 'Windows'], ['db', 'query', 'fortune', 'update']),
+]
+
+# All play2 test applications must use the same URLs.
+test_urls = {
+  'json': '/json',
+  'db': '/db',
+  'query': '/queries?queries=',
+  'fortune': '/fortunes',
+  'update': '/update?queries=',
+}
+
+tests_config_json = collections.OrderedDict()
+
+for lang, orm, oses, tests in configurations:
+  dir_name = 'play2-' + lang.lower() + (('-'+orm.lower()) if orm else '')
+  print 'Generating tests for test application '+dir_name
+  setup_name = 'setup_' + lang.lower() + (('_'+orm.lower()) if orm else '')
+  for os in oses:
+    if len(oses) == 1:
+      test_name = lang.lower() + (('-'+orm.lower()) if orm else '')
+    else:
+      test_name = lang.lower() + (('-'+orm.lower()) if orm else '') + '-'+os.lower()
+    test_config_json = collections.OrderedDict([
+      ('display_name', 'play2-'+test_name),
+      ('setup_file', setup_name),
+      ('framework', 'play2'),
+      ('language', lang),
+      ('orm', orm if orm else 'Raw'),
+      ('os', os),
+      ('database', 'MySQL' if orm else 'None'),
+      ('approach', 'Realistic'),
+      ('classification', 'Fullstack'),
+      ('platform', 'Netty'),
+      ('webserver', 'None'),
+      ('database_os', 'Linux'),
+      ('notes', ''),
+      ('versus', 'netty'),
+      ('port', '9000'),
+    ])
+    for test in tests:
+      test_config_json[test+'_url'] = test_urls[test]
+      tests_config_json[test_name] = test_config_json
+    with open(setup_name+'.py', 'w') as f:
+      f.write(textwrap.dedent("""
+        # This file was generated by generate_config.py.
+        # Do not edit this file directly.
+        from .setup_common import make_setup_for_dir
+
+        make_setup_for_dir(globals(), '"""+dir_name+"""')
+      """))
+
+with open('benchmark_config', 'w') as f:
+  json_str = json.dumps({
+    'framework': 'play2',
+    'tests': [tests_config_json]
+  }, indent=2)
+  f.write(json_str)

+ 3 - 0
frameworks/Java/play2-java/install.sh

@@ -0,0 +1,3 @@
+#!/bin/bash
+
+fw_depends java sbt

+ 30 - 0
frameworks/Java/play2-java/play2-java-ebean/.gitignore

@@ -0,0 +1,30 @@
+logs
+project/project
+project/target
+target
+tmp
+.history
+dist
+
+# Ignore all dotfiles...
+.*
+# except for .gitignore
+!.gitignore
+
+# Ignore Play! working directory #
+db
+eclipse
+lib
+log
+logs
+modules
+precompiled
+project/project
+project/target
+target
+tmp
+test-result
+server.pid
+*.iml
+*.eml
+

+ 20 - 0
frameworks/Java/play2-java/play2-java-ebean/README.md

@@ -0,0 +1,20 @@
+#Play Benchmarking Test
+
+This is the Play portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+
+### Data-Store/Database Mapping Test
+
+* [Database test controller](app/controllers/Application.java)
+* [Database test model](app/models/World.java)
+
+## Infrastructure Software Versions
+The tests were run with:
+
+* [Java OpenJDK 1.7](http://openjdk.java.net/)
+* [Play 2.2.0](http://http://www.playframework.com/)
+
+## Test URLs
+
+### Data-Store/Database Mapping Test
+
+http://localhost/db?queries=5

+ 97 - 0
frameworks/Java/play2-java/play2-java-ebean/app/controllers/Application.java

@@ -0,0 +1,97 @@
+package controllers;
+
+import akka.dispatch.ExecutionContexts;
+import models.World;
+import play.Play;
+import play.core.NamedThreadFactory;
+import play.libs.F;
+import play.libs.Json;
+
+import play.mvc.Controller;
+import play.mvc.Result;
+import scala.concurrent.ExecutionContext;
+import utils.Predicate;
+import utils.Predicated;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.*;
+
+public class Application extends Controller {
+
+    private static final int MAX_QUERIES_PER_REQUEST = 20;
+    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<Runnable>(),
+            new NamedThreadFactory("dbEc"));
+    private static final ExecutionContext dbEc = ExecutionContexts.fromExecutorService(tpe);
+
+    // 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;
+        }
+    }
+
+    @Predicated(predicate = IsDbAvailable.class, failed = SERVICE_UNAVAILABLE)
+    public static F.Promise<Result> db() {
+        return getRandomWorlds(1).map(new F.Function<List<World>, Result>() {
+            @Override
+            public Result apply(List<World> worlds) {
+                return ok(Json.toJson(worlds.get(0)));
+            }
+        });
+    }
+
+    @Predicated(predicate = IsDbAvailable.class, failed = SERVICE_UNAVAILABLE)
+    public static F.Promise<Result> queries(final String queryCountString) {
+        int queryCount;
+        try {
+            queryCount = Integer.parseInt(queryCountString, 10);
+        } catch (NumberFormatException e) {
+            queryCount = 1;
+        }
+        if (queryCount < 1) {
+            queryCount = 1;
+        } else if (queryCount > 500) {
+            queryCount = 500;
+        }
+
+        return getRandomWorlds(queryCount).map(new F.Function<List<World>, Result>() {
+            @Override
+            public Result apply(List<World> worlds) {
+                return ok(Json.toJson(worlds));
+            }
+        });
+    }
+
+    private static F.Promise<List<World>> getRandomWorlds(final int n) {
+        return F.Promise.promise(new F.Function0<List<World>>() {
+            @Override
+            public List<World> apply() {
+                Random random = ThreadLocalRandom.current();
+                List<World> worlds = new ArrayList<World>(n);
+                for (int i = 0; i < n; ++i) {
+                    long randomId = random.nextInt(TEST_DATABASE_ROWS) + 1;
+                    World world = World.find.byId(randomId);
+                    worlds.add(world);
+                }
+                return worlds;
+            }
+        }, dbEc);
+    }
+
+}

+ 20 - 0
frameworks/Java/play2-java/play2-java-ebean/app/models/World.java

@@ -0,0 +1,20 @@
+package models;
+
+import javax.persistence.*;
+
+import play.db.ebean.*;
+
+@Entity
+public class World extends Model {
+
+    @Id
+    public Long id;
+
+    @Column(name = "randomNumber")
+    public Long randomNumber;
+
+    public static Finder<Long, World> find = new Finder<Long, World>(
+            Long.class, World.class
+    );
+
+}

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

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

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

@@ -0,0 +1,26 @@
+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();
+}

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

@@ -0,0 +1,23 @@
+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.SimpleResult;
+
+public class PredicatedAction extends Action<Predicated> {
+    @Override
+    public F.Promise<SimpleResult> call(final Http.Context ctx) throws Throwable {
+        final Predicate p = configuration.predicate().newInstance();
+        if (p.condition()) {
+            return delegate.call(ctx);
+        } else {
+            return F.Promise.<SimpleResult>pure(status(configuration.failed()));
+        }
+    }
+}

+ 13 - 0
frameworks/Java/play2-java/play2-java-ebean/build.sbt

@@ -0,0 +1,13 @@
+name := "play2-java-ebean"
+
+version := "1.0-SNAPSHOT"
+
+libraryDependencies ++= Seq(
+  javaJdbc,
+  javaEbean,
+  "mysql" % "mysql-connector-java" % "5.1.22"
+  )
+
+dependencyOverrides += "com.jolbox" % "bonecp" % "0.7.1.RELEASE"
+
+playJavaSettings

+ 74 - 0
frameworks/Java/play2-java/play2-java-ebean/conf/application.conf

@@ -0,0 +1,74 @@
+# This is the main configuration file for the application.
+# ~~~~~
+
+# 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!
+application.secret="RItx1I:80?W@]8GAtPDuF8Ydd3mXM85p/<7og]Q;uBOdijQAauRDgu73B6`wQP59"
+
+# The application languages
+# ~~~~~
+application.langs="en"
+
+# Global object class
+# ~~~~~
+# Define the Global object class for this application.
+# Default to Global in the root package.
+# global=Global
+
+# 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://localhost: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.user=benchmarkdbuser
+db.default.password=benchmarkdbpass
+db.default.jndiName=DefaultDS
+
+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. 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.default.maxConnectionsPerPartition=64
+
+# The number of initial connections, per partition.
+db.default.minConnectionsPerPartition=64
+
+# Evolutions
+# ~~~~~
+# You can disable evolutions if needed
+evolutionplugin=disabled
+
+# Ebean configuration
+# ~~~~~
+# You can declare as many Ebean servers as you want.
+# By convention, the default server is named `default`
+#
+ebean.default="models.*"
+
+# Logger
+# ~~~~~
+# You can also configure logback (http://logback.qos.ch/), by providing a logger.xml file in the conf directory .
+
+# Root logger:
+logger.root=ERROR
+
+# Logger used by the framework:
+logger.play=ERROR
+
+# Logger provided to your application:
+logger.application=ERROR
+

+ 10 - 0
frameworks/Java/play2-java/play2-java-ebean/conf/routes

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

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

@@ -0,0 +1 @@
+sbt.version=0.13.0

+ 8 - 0
frameworks/Java/play2-java/play2-java-ebean/project/plugins.sbt

@@ -0,0 +1,8 @@
+// Comment to get more information during initialization
+logLevel := Level.Warn
+
+// The Typesafe repository 
+resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
+
+// Use the Play sbt plugin for Play projects
+addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.2.0")

+ 9 - 0
frameworks/Java/play2-java/play2-java-ebean/source_code

@@ -0,0 +1,9 @@
+./play-java/app/
+./play-java/app/controllers
+./play-java/app/controllers/Application.java
+./play-java/app/utils
+./play-java/app/utils/Predicate.java
+./play-java/app/utils/PredicatedAction.java
+./play-java/app/utils/Predicated.java
+./play-java/app/models
+./play-java/app/models/World.java

+ 30 - 0
frameworks/Java/play2-java/play2-java/.gitignore

@@ -0,0 +1,30 @@
+logs
+project/project
+project/target
+target
+tmp
+.history
+dist
+
+# Ignore all dotfiles...
+.*
+# except for .gitignore
+!.gitignore
+
+# Ignore Play! working directory #
+db
+eclipse
+lib
+log
+logs
+modules
+precompiled
+project/project
+project/target
+target
+tmp
+test-result
+server.pid
+*.iml
+*.eml
+

+ 18 - 0
frameworks/Java/play2-java/play2-java/README.md

@@ -0,0 +1,18 @@
+#Play Benchmarking Test
+
+This is the Play portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+
+### JSON Encoding Test
+
+* [JSON test source](app/controllers/Application.java)
+
+## Infrastructure Software Versions
+The tests were run with:
+
+* [Java OpenJDK 1.7.0_09](http://openjdk.java.net/)
+* [Play 2](http://http://www.playframework.com/)
+
+## Test URLs
+### JSON Encoding Test
+
+http://localhost/json

+ 19 - 0
frameworks/Java/play2-java/play2-java/app/controllers/Application.java

@@ -0,0 +1,19 @@
+package controllers;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import play.mvc.Controller;
+import play.mvc.Result;
+
+public class Application extends Controller {
+
+    //http://stackoverflow.com/questions/3907929/should-i-make-jacksons-objectmapper-as-static-final
+    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
+
+    public static Result json() {
+        final ObjectNode result = OBJECT_MAPPER.createObjectNode();
+        result.put("message", "Hello, World!");
+        return ok(result);
+    }
+
+}

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

@@ -0,0 +1,5 @@
+name := "play2-java"
+
+version := "1.0-SNAPSHOT"
+
+lazy val root = (project in file(".")).enablePlugins(PlayJava)

+ 26 - 0
frameworks/Java/play2-java/play2-java/conf/application.conf

@@ -0,0 +1,26 @@
+# This is the main configuration file for the application.
+# ~~~~~
+
+# 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!
+application.secret="RItx1I:80?W@]8GAtPDuF8Ydd3mXM85p/<7og]Q;uBOdijQAauRDgu73B6`wQP59"
+
+# The application languages
+# ~~~~~
+application.langs="en"
+
+# Logger
+# ~~~~~
+# You can also configure logback (http://logback.qos.ch/), by providing a logger.xml file in the conf directory .
+
+# Root logger:
+logger.root=ERROR
+
+# Logger used by the framework:
+logger.play=ERROR
+
+# Logger provided to your application:
+logger.application=ERROR
+

+ 9 - 0
frameworks/Java/play2-java/play2-java/conf/routes

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

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

@@ -0,0 +1 @@
+sbt.version=0.13.5

+ 8 - 0
frameworks/Java/play2-java/play2-java/project/plugins.sbt

@@ -0,0 +1,8 @@
+// Comment to get more information during initialization
+logLevel := Level.Warn
+
+// The Typesafe repository 
+resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
+
+// Use the Play sbt plugin for Play projects
+addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.2")

+ 9 - 0
frameworks/Java/play2-java/play2-java/source_code

@@ -0,0 +1,9 @@
+./play-java/app/
+./play-java/app/controllers
+./play-java/app/controllers/Application.java
+./play-java/app/utils
+./play-java/app/utils/Predicate.java
+./play-java/app/utils/PredicatedAction.java
+./play-java/app/utils/Predicated.java
+./play-java/app/models
+./play-java/app/models/World.java

+ 33 - 0
frameworks/Java/play2-java/play2-scala-anorm/.gitignore

@@ -0,0 +1,33 @@
+logs
+project/project
+project/target
+public
+target
+test
+tmp
+.history
+dist
+conf/evolutions
+
+# Ignore all dotfiles...
+.*
+# except for .gitignore
+!.gitignore
+
+# Ignore Play! working directory #
+db
+eclipse
+lib
+log
+logs
+modules
+precompiled
+project/project
+project/target
+target
+tmp
+test-result
+server.pid
+*.iml
+*.eml
+

+ 20 - 0
frameworks/Java/play2-java/play2-scala-anorm/README.md

@@ -0,0 +1,20 @@
+#Play Benchmarking Test
+
+This is the Play portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+
+### Data-Store/Database Mapping Test
+
+* [Database test controller](app/controllers/Application.scala)
+* [Database test model](app/models/World.scala)
+
+## Infrastructure Software Versions
+The tests were run with:
+
+* [Java OpenJDK 1.7.0_09](http://openjdk.java.net/)
+* [Play 2](http://http://www.playframework.com/)
+
+## Test URLs
+
+### Data-Store/Database Mapping Test
+
+http://localhost/db?queries=5

+ 106 - 0
frameworks/Java/play2-java/play2-scala-anorm/app/controllers/Application.scala

@@ -0,0 +1,106 @@
+package controllers
+
+import play.api.Play.current
+import play.api.db.DB
+import play.api.mvc._
+import play.api.libs.json.Json
+import java.util.concurrent._
+import scala.concurrent._
+import models.{World, Fortune}
+import utils._
+import scala.concurrent.Future
+
+import play.api.libs.concurrent.Execution.Implicits._
+import play.core.NamedThreadFactory
+
+object Application extends Controller {
+
+  private val TestDatabaseRows = 10000
+
+  private val partitionCount = current.configuration.getInt("db.default.partitionCount").getOrElse(2)
+  private val maxConnections =
+    partitionCount * current.configuration.getInt("db.default.maxConnectionsPerPartition").getOrElse(5)
+  private val minConnections =
+    partitionCount * current.configuration.getInt("db.default.minConnectionsPerPartition").getOrElse(5)
+
+  private val tpe = new ThreadPoolExecutor(minConnections, maxConnections,
+    0L, TimeUnit.MILLISECONDS,
+    new LinkedBlockingQueue[Runnable](),
+    new NamedThreadFactory("dbEc"))
+  private val dbEc = ExecutionContext.fromExecutorService(tpe)
+
+  // 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.
+  def isDbQueueTooBig: Boolean = tpe.getQueue.size() <= 1024
+
+  def db = PredicatedAction(isDbQueueTooBig, ServiceUnavailable) {
+    Action.async {
+      getRandomWorlds(1).map { worlds =>
+        Ok(Json.toJson(worlds.head))
+      }
+    }
+  }
+
+  def queries(countString: String) = PredicatedAction(isDbQueueTooBig, ServiceUnavailable) {
+    Action.async {
+      val n = parseCount(countString)
+      getRandomWorlds(n).map { worlds =>
+        Ok(Json.toJson(worlds))
+      }
+    }
+  }
+
+  private def parseCount(s: String): Int = {
+    try {
+      val parsed = java.lang.Integer.parseInt(s, 10)
+      parsed match {
+        case i if i < 1 => 1
+        case i if i > 500 => 500
+        case i => i
+      }
+    } catch {
+      case _: NumberFormatException => 1
+    }
+  }
+
+  private def getRandomWorlds(n: Int): Future[Seq[World]] = Future {
+    val random = ThreadLocalRandom.current()
+    DB.withConnection { implicit connection =>
+      for (_ <- 1 to n) yield {
+        val randomId: Long = random.nextInt(TestDatabaseRows) + 1
+        World.findById(randomId)
+      }
+    }
+  }(dbEc)
+
+  def fortunes() = PredicatedAction(isDbQueueTooBig, ServiceUnavailable) {
+    Action.async {
+      Future {
+        val fortunes = Fortune.getAll()
+        val extendedFortunes = Fortune(0.toLong, "Additional fortune added at request time.") +: fortunes
+        Ok(views.html.fortune(extendedFortunes))
+      }
+    }
+  }
+
+  def update(countString: String) = PredicatedAction(isDbQueueTooBig, ServiceUnavailable) {
+    Action.async {
+      val n = parseCount(countString)
+      Future {
+        val random = ThreadLocalRandom.current()
+        val worlds = DB.withConnection { implicit connection =>
+          for(_ <- 1 to n) yield {
+            val randomId: Long = random.nextInt(TestDatabaseRows) + 1
+            val world = World.findById(random.nextInt(TestDatabaseRows) + 1)
+            val updatedWorld = world.copy(randomNumber = random.nextInt(10000) + 1)
+            World.updateRandom(updatedWorld)
+            updatedWorld
+          }
+        }
+        Ok(Json.toJson(worlds)).withHeaders("Server" -> "Netty")
+      }(dbEc)
+    }
+  }
+}

+ 25 - 0
frameworks/Java/play2-java/play2-scala-anorm/app/models/Fortune.scala

@@ -0,0 +1,25 @@
+package models
+
+import play.api.db._
+import play.api.Play.current
+import anorm._
+import anorm.SqlParser._
+import scala.language.postfixOps
+
+case class Fortune(id: Long, message: String)
+
+object Fortune {
+
+  val simpleRowParser = {
+    get[Long]("fortune.id") ~
+    get[String]("fortune.message") map {
+      case id~message => Fortune(id, message)
+    }
+  }
+
+  def getAll(): List[Fortune] = {
+    DB.withConnection { implicit connection =>
+      SQL("SELECT * FROM Fortune").as(Fortune.simpleRowParser *)
+    }
+  }
+}

+ 55 - 0
frameworks/Java/play2-java/play2-scala-anorm/app/models/World.scala

@@ -0,0 +1,55 @@
+package models
+
+import anorm._
+import anorm.SqlParser._
+import java.sql.Connection
+import play.api.db._
+import play.api.libs.functional.syntax._
+import play.api.libs.json._
+import play.api.Play.current
+
+case class World(id: Pk[Long], randomNumber: Long)
+
+object World {
+    /**
+    * Convert a World to Json object
+    */
+  implicit val toJson = new Writes[World] {
+    def writes(w: World): JsValue = {
+      Json.obj(
+        "id" -> w.id.get,
+        "randomNumber" -> w.randomNumber
+      )
+    }
+  }
+
+  /**
+   * Parse a World from a ResultSet
+   */
+  val simpleRowParser = {
+    get[Pk[Long]]("world.id") ~
+    get[Long]("world.randomNumber") map {
+      case id~randomNumber => World(id, randomNumber)
+    }
+  }
+
+  /**
+   * Retrieve a World by id.
+   */
+  def findById(id: Long)(implicit connection: Connection): World = {
+    DB.withConnection { implicit connection =>
+      SQL("SELECT * FROM World WHERE id = {id}").on(
+          "id" -> id
+      ).as(World.simpleRowParser.single)
+    }
+  }
+
+  def updateRandom(world: World)(implicit connection: Connection) {
+    DB.withConnection { implicit connection =>
+      SQL("UPDATE World SET randomNumber = {randomNumber} WHERE id = {id}").on(
+        "id" -> world.id.get,
+        "randomNumber" -> world.randomNumber
+      ).executeUpdate()
+    }
+  }
+}

+ 20 - 0
frameworks/Java/play2-java/play2-scala-anorm/app/utils/PredicatedAction.scala

@@ -0,0 +1,20 @@
+package utils
+
+import play.api.mvc._
+import scala.concurrent.{Promise, Future}
+
+/**
+ * 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.
+ */
+class PredicatedActionBuilder {
+  def apply[A](p: => Boolean, failed: => SimpleResult)(action: Action[A]): Action[A] = new Action[A] {
+    def apply(request: Request[A]): Future[SimpleResult] = {
+      if (p) action(request) else Promise.successful(failed).future
+    }
+
+    lazy val parser = action.parser
+  }
+}
+
+object PredicatedAction extends PredicatedActionBuilder

+ 18 - 0
frameworks/Java/play2-java/play2-scala-anorm/app/views/fortune.scala.html

@@ -0,0 +1,18 @@
+@(fortunes: List[Fortune])
+
+@main("Fortunes") {
+    <table>
+        <tr>
+            <th>id</th>
+            <th>message</th>
+        </tr>
+
+        @fortunes.sortBy(_.message).map { case Fortune(id, message) =>
+            <tr>
+                <td>@id</td>
+                <td>@message</td>
+            </tr>
+        }
+
+    </table>
+}

+ 12 - 0
frameworks/Java/play2-java/play2-scala-anorm/app/views/main.scala.html

@@ -0,0 +1,12 @@
+@(title: String)(content: Html)
+
+<!DOCTYPE html>
+
+<html>
+<head>
+    <title>@title</title>
+</head>
+<body>
+    @content
+</body>
+</html>

+ 9 - 0
frameworks/Java/play2-java/play2-scala-anorm/build.sbt

@@ -0,0 +1,9 @@
+name := "play2-scala-anorm"
+
+version := "1.0-SNAPSHOT"
+
+libraryDependencies ++= Seq(jdbc, anorm, "mysql" % "mysql-connector-java" % "5.1.22")
+
+dependencyOverrides += "com.jolbox" % "bonecp" % "0.7.1.RELEASE"
+
+playScalaSettings

+ 66 - 0
frameworks/Java/play2-java/play2-scala-anorm/conf/application.conf

@@ -0,0 +1,66 @@
+# This is the main configuration file for the application.
+# ~~~~~
+
+# 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!
+application.secret="RItx1I:80?W@]8GAtPDuF8Ydd3mXM85p/<7og]Q;uBOdijQAauRDgu73B6`wQP59"
+
+# The application languages
+# ~~~~~
+application.langs="en"
+
+# Global object class
+# ~~~~~
+# Define the Global object class for this application.
+# Default to Global in the root package.
+# global=Global
+
+# 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://!!DATABASE_HOST!!: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.user=benchmarkdbuser
+db.default.password=benchmarkdbpass
+db.default.jndiName=DefaultDS
+
+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. 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.default.maxConnectionsPerPartition=64
+
+# The number of initial connections, per partition.
+db.default.minConnectionsPerPartition=64
+
+# Evolutions
+# ~~~~~
+# You can disable evolutions if needed
+# evolutionplugin=disabled
+
+# Logger
+# ~~~~~
+# You can also configure logback (http://logback.qos.ch/), by providing a logger.xml file in the conf directory .
+
+# Root logger:
+logger.root=ERROR
+
+# Logger used by the framework:
+logger.play=ERROR
+
+# Logger provided to your application:
+logger.application=ERROR

+ 12 - 0
frameworks/Java/play2-java/play2-scala-anorm/conf/routes

@@ -0,0 +1,12 @@
+# Routes
+# 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     /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)

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

@@ -0,0 +1 @@
+sbt.version=0.13.0

+ 8 - 0
frameworks/Java/play2-java/play2-scala-anorm/project/plugins.sbt

@@ -0,0 +1,8 @@
+// Comment to get more information during initialization
+logLevel := Level.Warn
+
+// The Typesafe repository 
+resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
+
+// Use the Play sbt plugin for Play projects
+addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.2.0")

+ 11 - 0
frameworks/Java/play2-java/play2-scala-anorm/source_code

@@ -0,0 +1,11 @@
+./play-scala/app/
+./play-scala/app/controllers
+./play-scala/app/controllers/Application.scala
+./play-scala/app/views
+./play-scala/app/views/main.scala.html
+./play-scala/app/views/fortune.scala.html
+./play-scala/app/utils
+./play-scala/app/utils/PredicatedAction.scala
+./play-scala/app/models
+./play-scala/app/models/Fortune.scala
+./play-scala/app/models/World.scala

+ 33 - 0
frameworks/Java/play2-java/play2-scala/.gitignore

@@ -0,0 +1,33 @@
+logs
+project/project
+project/target
+public
+target
+test
+tmp
+.history
+dist
+conf/evolutions
+
+# Ignore all dotfiles...
+.*
+# except for .gitignore
+!.gitignore
+
+# Ignore Play! working directory #
+db
+eclipse
+lib
+log
+logs
+modules
+precompiled
+project/project
+project/target
+target
+tmp
+test-result
+server.pid
+*.iml
+*.eml
+

+ 18 - 0
frameworks/Java/play2-java/play2-scala/README.md

@@ -0,0 +1,18 @@
+#Play Benchmarking Test
+
+This is the Play portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+
+### JSON Encoding Test
+
+* [JSON test source](app/controllers/Application.scala)
+
+## Infrastructure Software Versions
+The tests were run with:
+
+* [Java OpenJDK 1.7.0_09](http://openjdk.java.net/)
+* [Play 2](http://http://www.playframework.com/)
+
+## Test URLs
+### JSON Encoding Test
+
+http://localhost/json

+ 12 - 0
frameworks/Java/play2-java/play2-scala/app/controllers/Application.scala

@@ -0,0 +1,12 @@
+package controllers
+
+import play.api.mvc._
+import play.api.libs.json.Json
+
+object Application extends Controller {
+
+  def json() = Action {
+    Ok(Json.obj("message" -> "Hello, World!"))
+  }
+
+}

+ 5 - 0
frameworks/Java/play2-java/play2-scala/build.sbt

@@ -0,0 +1,5 @@
+name := "play2-scala"
+
+version := "1.0-SNAPSHOT"
+
+lazy val root = (project in file(".")).enablePlugins(PlayScala)

+ 31 - 0
frameworks/Java/play2-java/play2-scala/conf/application.conf

@@ -0,0 +1,31 @@
+# This is the main configuration file for the application.
+# ~~~~~
+
+# 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!
+application.secret="RItx1I:80?W@]8GAtPDuF8Ydd3mXM85p/<7og]Q;uBOdijQAauRDgu73B6`wQP59"
+
+# The application languages
+# ~~~~~
+application.langs="en"
+
+# Global object class
+# ~~~~~
+# Define the Global object class for this application.
+# Default to Global in the root package.
+# global=Global
+
+# Logger
+# ~~~~~
+# You can also configure logback (http://logback.qos.ch/), by providing a logger.xml file in the conf directory .
+
+# Root logger:
+logger.root=ERROR
+
+# Logger used by the framework:
+logger.play=ERROR
+
+# Logger provided to your application:
+logger.application=ERROR

+ 9 - 0
frameworks/Java/play2-java/play2-scala/conf/routes

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

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

@@ -0,0 +1 @@
+sbt.version=0.13.5

+ 8 - 0
frameworks/Java/play2-java/play2-scala/project/plugins.sbt

@@ -0,0 +1,8 @@
+// Comment to get more information during initialization
+logLevel := Level.Warn
+
+// The Typesafe repository 
+resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
+
+// Use the Play sbt plugin for Play projects
+addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.2")

+ 11 - 0
frameworks/Java/play2-java/play2-scala/source_code

@@ -0,0 +1,11 @@
+./play-scala/app/
+./play-scala/app/controllers
+./play-scala/app/controllers/Application.scala
+./play-scala/app/views
+./play-scala/app/views/main.scala.html
+./play-scala/app/views/fortune.scala.html
+./play-scala/app/utils
+./play-scala/app/utils/PredicatedAction.scala
+./play-scala/app/models
+./play-scala/app/models/Fortune.scala
+./play-scala/app/models/World.scala

+ 55 - 0
frameworks/Java/play2-java/setup_common.py

@@ -0,0 +1,55 @@
+import os, setup_util, signal, subprocess
+
+# Create start and stop functions for the Play project with the given dir
+# and install them in the given module's globals.
+def make_setup_for_dir(module_globals, subtest_name):
+
+  def start(args, logfile, errfile):
+    kill_running_process(logfile)
+
+    subtest_dir = get_subtest_dir()
+    install_dir = os.environ['IROOT']
+
+    is_windows = os.name == "nt"
+    cmd_suffix = '.bat' if is_windows else ''
+    sbt_cmd = os.path.join(install_dir, 'sbt', 'bin', 'sbt'+cmd_suffix)
+    app_cmd = os.path.join(subtest_dir, 'target','universal','stage','bin',subtest_name+cmd_suffix)
+
+    setup_util.replace_text(
+      os.path.join(subtest_dir,'conf','application.conf'),
+      "jdbc:mysql:\/\/.*:3306", "jdbc:mysql://" + args.database_host + ":3306")
+    logfile.write('Staging app: '+sbt_cmd+' stage\n')
+    subprocess.call(
+      [sbt_cmd, 'stage'],
+      stdin=subprocess.PIPE, cwd=subtest_dir, stderr=errfile, stdout=logfile)
+    logfile.write('Starting app: '+app_cmd+'\n')
+    subprocess.Popen(
+      [app_cmd],
+      shell=True, stdin=subprocess.PIPE, cwd=subtest_dir, stderr=errfile, stdout=logfile)
+    return 0
+
+  def stop(logfile, errfile):
+    kill_running_process(logfile)  
+    return 0
+
+  # Install the start and stop functions in the calling module
+  module_globals['start'] = start
+  module_globals['stop'] = stop
+
+  def get_subtest_dir():
+    test_dir = os.environ['TROOT']
+    return os.path.join(test_dir, subtest_name)
+
+  # Kill the running process and delete the RUNNING_PID file (if any).
+  def kill_running_process(logfile):
+    subtest_dir = get_subtest_dir()
+    pidfile = os.path.join(subtest_dir,"target","universal","stage","RUNNING_PID")
+    if not os.path.exists(pidfile):
+      logfile.write('No PID file: {}\n'.format(pidfile))
+      return
+    logfile.write('Reading and deleting PID file: {}\n'.format(pidfile))
+    with open(pidfile) as f:
+      pid = int(f.read())
+    os.remove(pidfile)
+    logfile.write('Sending SIGTERM to process: {}\n'.format(pid))
+    os.kill(pid, signal.SIGTERM)

+ 6 - 0
frameworks/Java/play2-java/setup_java.py

@@ -0,0 +1,6 @@
+
+# This file was generated by generate_config.py.
+# Do not edit this file directly.
+from .setup_common import make_setup_for_dir
+
+make_setup_for_dir(globals(), 'play2-java')

+ 6 - 0
frameworks/Java/play2-java/setup_java_ebean.py

@@ -0,0 +1,6 @@
+
+# This file was generated by generate_config.py.
+# Do not edit this file directly.
+from .setup_common import make_setup_for_dir
+
+make_setup_for_dir(globals(), 'play2-java-ebean')

+ 6 - 0
frameworks/Java/play2-java/setup_scala.py

@@ -0,0 +1,6 @@
+
+# This file was generated by generate_config.py.
+# Do not edit this file directly.
+from .setup_common import make_setup_for_dir
+
+make_setup_for_dir(globals(), 'play2-scala')

+ 6 - 0
frameworks/Java/play2-java/setup_scala_anorm.py

@@ -0,0 +1,6 @@
+
+# This file was generated by generate_config.py.
+# Do not edit this file directly.
+from .setup_common import make_setup_for_dir
+
+make_setup_for_dir(globals(), 'play2-scala-anorm')

+ 5 - 0
frameworks/Scala/play2-scala/README.md

@@ -0,0 +1,5 @@
+# play2 framework tests
+
+1. Add new test applications in subdirectories named either `play2-language` or `play2-language-orm`.
+2. Edit `generate_config.py` and add configuration for the new test applications.
+3. Run `python generate_config.py` to generate a new `benchmark_config` file and to generate a `setup_play2_*.py` file for your test application.

+ 0 - 0
frameworks/Scala/play2-scala/__init__.py


+ 1 - 0
frameworks/Scala/play2-scala/bash_profile.sh

@@ -0,0 +1 @@
+# Intentionally blank

+ 104 - 0
frameworks/Scala/play2-scala/benchmark_config

@@ -0,0 +1,104 @@
+{
+  "framework": "play2", 
+  "tests": [
+    {
+      "java": {
+        "display_name": "play2-java", 
+        "setup_file": "setup_java", 
+        "framework": "play2", 
+        "language": "Java", 
+        "orm": "Raw", 
+        "os": "Linux", 
+        "database": "None", 
+        "approach": "Realistic", 
+        "classification": "Fullstack", 
+        "platform": "Netty", 
+        "webserver": "None", 
+        "database_os": "Linux", 
+        "notes": "", 
+        "versus": "netty", 
+        "port": "9000", 
+        "json_url": "/json"
+      }, 
+      "scala": {
+        "display_name": "play2-scala", 
+        "setup_file": "setup_scala", 
+        "framework": "play2", 
+        "language": "Scala", 
+        "orm": "Raw", 
+        "os": "Linux", 
+        "database": "None", 
+        "approach": "Realistic", 
+        "classification": "Fullstack", 
+        "platform": "Netty", 
+        "webserver": "None", 
+        "database_os": "Linux", 
+        "notes": "", 
+        "versus": "netty", 
+        "port": "9000", 
+        "json_url": "/json"
+      }, 
+      "java-ebean": {
+        "display_name": "play2-java-ebean", 
+        "setup_file": "setup_java_ebean", 
+        "framework": "play2", 
+        "language": "Java", 
+        "orm": "Ebean", 
+        "os": "Linux", 
+        "database": "MySQL", 
+        "approach": "Realistic", 
+        "classification": "Fullstack", 
+        "platform": "Netty", 
+        "webserver": "None", 
+        "database_os": "Linux", 
+        "notes": "", 
+        "versus": "netty", 
+        "port": "9000", 
+        "db_url": "/db", 
+        "query_url": "/queries?queries="
+      }, 
+      "scala-anorm-linux": {
+        "display_name": "play2-scala-anorm-linux", 
+        "setup_file": "setup_scala_anorm", 
+        "framework": "play2", 
+        "language": "Scala", 
+        "orm": "Anorm", 
+        "os": "Linux", 
+        "database": "MySQL", 
+        "approach": "Realistic", 
+        "classification": "Fullstack", 
+        "platform": "Netty", 
+        "webserver": "None", 
+        "database_os": "Linux", 
+        "notes": "", 
+        "versus": "netty", 
+        "port": "9000", 
+        "db_url": "/db", 
+        "query_url": "/queries?queries=", 
+        "fortune_url": "/fortunes", 
+        "update_url": "/update?queries="
+      }, 
+      "scala-anorm-windows": {
+        "display_name": "play2-scala-anorm-windows", 
+        "setup_file": "setup_scala_anorm", 
+        "framework": "play2", 
+        "language": "Scala", 
+        "orm": "Anorm", 
+        "os": "Windows", 
+        "database": "MySQL", 
+        "approach": "Realistic", 
+        "classification": "Fullstack", 
+        "platform": "Netty", 
+        "webserver": "None", 
+        "database_os": "Linux", 
+        "notes": "", 
+        "versus": "netty", 
+        "port": "9000", 
+        "db_url": "/db", 
+        "query_url": "/queries?queries=", 
+        "fortune_url": "/fortunes", 
+        "update_url": "/update?queries="
+      }
+    }
+  ]
+}

+ 72 - 0
frameworks/Scala/play2-scala/generate_config.py

@@ -0,0 +1,72 @@
+#!/usr/bin/env python
+
+import collections, json, textwrap
+
+# This script generates the benchmark_config and setup_*.py files.
+# To add new tests, modify the `configurations` and `test_urls` tables.
+
+# Each line corresponds to a test application.
+# Format is: (language, orm, (os, ...), (test, ...))
+# See the dir_name logic below to see the directory name for each test application.
+configurations = [
+  ('Java',  None,    ['Linux'],            ['json']),
+  ('Scala', None,    ['Linux'],            ['json']),
+  ('Java',  'Ebean', ['Linux'],            ['db', 'query']),
+  ('Scala', 'Anorm', ['Linux', 'Windows'], ['db', 'query', 'fortune', 'update']),
+]
+
+# All play2 test applications must use the same URLs.
+test_urls = {
+  'json': '/json',
+  'db': '/db',
+  'query': '/queries?queries=',
+  'fortune': '/fortunes',
+  'update': '/update?queries=',
+}
+
+tests_config_json = collections.OrderedDict()
+
+for lang, orm, oses, tests in configurations:
+  dir_name = 'play2-' + lang.lower() + (('-'+orm.lower()) if orm else '')
+  print 'Generating tests for test application '+dir_name
+  setup_name = 'setup_' + lang.lower() + (('_'+orm.lower()) if orm else '')
+  for os in oses:
+    if len(oses) == 1:
+      test_name = lang.lower() + (('-'+orm.lower()) if orm else '')
+    else:
+      test_name = lang.lower() + (('-'+orm.lower()) if orm else '') + '-'+os.lower()
+    test_config_json = collections.OrderedDict([
+      ('display_name', 'play2-'+test_name),
+      ('setup_file', setup_name),
+      ('framework', 'play2'),
+      ('language', lang),
+      ('orm', orm if orm else 'Raw'),
+      ('os', os),
+      ('database', 'MySQL' if orm else 'None'),
+      ('approach', 'Realistic'),
+      ('classification', 'Fullstack'),
+      ('platform', 'Netty'),
+      ('webserver', 'None'),
+      ('database_os', 'Linux'),
+      ('notes', ''),
+      ('versus', 'netty'),
+      ('port', '9000'),
+    ])
+    for test in tests:
+      test_config_json[test+'_url'] = test_urls[test]
+      tests_config_json[test_name] = test_config_json
+    with open(setup_name+'.py', 'w') as f:
+      f.write(textwrap.dedent("""
+        # This file was generated by generate_config.py.
+        # Do not edit this file directly.
+        from .setup_common import make_setup_for_dir
+
+        make_setup_for_dir(globals(), '"""+dir_name+"""')
+      """))
+
+with open('benchmark_config', 'w') as f:
+  json_str = json.dumps({
+    'framework': 'play2',
+    'tests': [tests_config_json]
+  }, indent=2)
+  f.write(json_str)

+ 3 - 0
frameworks/Scala/play2-scala/install.sh

@@ -0,0 +1,3 @@
+#!/bin/bash
+
+fw_depends java sbt

+ 30 - 0
frameworks/Scala/play2-scala/play2-java-ebean/.gitignore

@@ -0,0 +1,30 @@
+logs
+project/project
+project/target
+target
+tmp
+.history
+dist
+
+# Ignore all dotfiles...
+.*
+# except for .gitignore
+!.gitignore
+
+# Ignore Play! working directory #
+db
+eclipse
+lib
+log
+logs
+modules
+precompiled
+project/project
+project/target
+target
+tmp
+test-result
+server.pid
+*.iml
+*.eml
+

+ 20 - 0
frameworks/Scala/play2-scala/play2-java-ebean/README.md

@@ -0,0 +1,20 @@
+#Play Benchmarking Test
+
+This is the Play portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+
+### Data-Store/Database Mapping Test
+
+* [Database test controller](app/controllers/Application.java)
+* [Database test model](app/models/World.java)
+
+## Infrastructure Software Versions
+The tests were run with:
+
+* [Java OpenJDK 1.7](http://openjdk.java.net/)
+* [Play 2.2.0](http://http://www.playframework.com/)
+
+## Test URLs
+
+### Data-Store/Database Mapping Test
+
+http://localhost/db?queries=5

+ 97 - 0
frameworks/Scala/play2-scala/play2-java-ebean/app/controllers/Application.java

@@ -0,0 +1,97 @@
+package controllers;
+
+import akka.dispatch.ExecutionContexts;
+import models.World;
+import play.Play;
+import play.core.NamedThreadFactory;
+import play.libs.F;
+import play.libs.Json;
+
+import play.mvc.Controller;
+import play.mvc.Result;
+import scala.concurrent.ExecutionContext;
+import utils.Predicate;
+import utils.Predicated;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.*;
+
+public class Application extends Controller {
+
+    private static final int MAX_QUERIES_PER_REQUEST = 20;
+    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<Runnable>(),
+            new NamedThreadFactory("dbEc"));
+    private static final ExecutionContext dbEc = ExecutionContexts.fromExecutorService(tpe);
+
+    // 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;
+        }
+    }
+
+    @Predicated(predicate = IsDbAvailable.class, failed = SERVICE_UNAVAILABLE)
+    public static F.Promise<Result> db() {
+        return getRandomWorlds(1).map(new F.Function<List<World>, Result>() {
+            @Override
+            public Result apply(List<World> worlds) {
+                return ok(Json.toJson(worlds.get(0)));
+            }
+        });
+    }
+
+    @Predicated(predicate = IsDbAvailable.class, failed = SERVICE_UNAVAILABLE)
+    public static F.Promise<Result> queries(final String queryCountString) {
+        int queryCount;
+        try {
+            queryCount = Integer.parseInt(queryCountString, 10);
+        } catch (NumberFormatException e) {
+            queryCount = 1;
+        }
+        if (queryCount < 1) {
+            queryCount = 1;
+        } else if (queryCount > 500) {
+            queryCount = 500;
+        }
+
+        return getRandomWorlds(queryCount).map(new F.Function<List<World>, Result>() {
+            @Override
+            public Result apply(List<World> worlds) {
+                return ok(Json.toJson(worlds));
+            }
+        });
+    }
+
+    private static F.Promise<List<World>> getRandomWorlds(final int n) {
+        return F.Promise.promise(new F.Function0<List<World>>() {
+            @Override
+            public List<World> apply() {
+                Random random = ThreadLocalRandom.current();
+                List<World> worlds = new ArrayList<World>(n);
+                for (int i = 0; i < n; ++i) {
+                    long randomId = random.nextInt(TEST_DATABASE_ROWS) + 1;
+                    World world = World.find.byId(randomId);
+                    worlds.add(world);
+                }
+                return worlds;
+            }
+        }, dbEc);
+    }
+
+}

+ 20 - 0
frameworks/Scala/play2-scala/play2-java-ebean/app/models/World.java

@@ -0,0 +1,20 @@
+package models;
+
+import javax.persistence.*;
+
+import play.db.ebean.*;
+
+@Entity
+public class World extends Model {
+
+    @Id
+    public Long id;
+
+    @Column(name = "randomNumber")
+    public Long randomNumber;
+
+    public static Finder<Long, World> find = new Finder<Long, World>(
+            Long.class, World.class
+    );
+
+}

+ 8 - 0
frameworks/Scala/play2-scala/play2-java-ebean/app/utils/Predicate.java

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

+ 26 - 0
frameworks/Scala/play2-scala/play2-java-ebean/app/utils/Predicated.java

@@ -0,0 +1,26 @@
+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();
+}

+ 23 - 0
frameworks/Scala/play2-scala/play2-java-ebean/app/utils/PredicatedAction.java

@@ -0,0 +1,23 @@
+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.SimpleResult;
+
+public class PredicatedAction extends Action<Predicated> {
+    @Override
+    public F.Promise<SimpleResult> call(final Http.Context ctx) throws Throwable {
+        final Predicate p = configuration.predicate().newInstance();
+        if (p.condition()) {
+            return delegate.call(ctx);
+        } else {
+            return F.Promise.<SimpleResult>pure(status(configuration.failed()));
+        }
+    }
+}

+ 13 - 0
frameworks/Scala/play2-scala/play2-java-ebean/build.sbt

@@ -0,0 +1,13 @@
+name := "play2-java-ebean"
+
+version := "1.0-SNAPSHOT"
+
+libraryDependencies ++= Seq(
+  javaJdbc,
+  javaEbean,
+  "mysql" % "mysql-connector-java" % "5.1.22"
+  )
+
+dependencyOverrides += "com.jolbox" % "bonecp" % "0.7.1.RELEASE"
+
+playJavaSettings

+ 74 - 0
frameworks/Scala/play2-scala/play2-java-ebean/conf/application.conf

@@ -0,0 +1,74 @@
+# This is the main configuration file for the application.
+# ~~~~~
+
+# 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!
+application.secret="RItx1I:80?W@]8GAtPDuF8Ydd3mXM85p/<7og]Q;uBOdijQAauRDgu73B6`wQP59"
+
+# The application languages
+# ~~~~~
+application.langs="en"
+
+# Global object class
+# ~~~~~
+# Define the Global object class for this application.
+# Default to Global in the root package.
+# global=Global
+
+# 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://localhost: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.user=benchmarkdbuser
+db.default.password=benchmarkdbpass
+db.default.jndiName=DefaultDS
+
+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. 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.default.maxConnectionsPerPartition=64
+
+# The number of initial connections, per partition.
+db.default.minConnectionsPerPartition=64
+
+# Evolutions
+# ~~~~~
+# You can disable evolutions if needed
+evolutionplugin=disabled
+
+# Ebean configuration
+# ~~~~~
+# You can declare as many Ebean servers as you want.
+# By convention, the default server is named `default`
+#
+ebean.default="models.*"
+
+# Logger
+# ~~~~~
+# You can also configure logback (http://logback.qos.ch/), by providing a logger.xml file in the conf directory .
+
+# Root logger:
+logger.root=ERROR
+
+# Logger used by the framework:
+logger.play=ERROR
+
+# Logger provided to your application:
+logger.application=ERROR
+

+ 10 - 0
frameworks/Scala/play2-scala/play2-java-ebean/conf/routes

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

+ 1 - 0
frameworks/Scala/play2-scala/play2-java-ebean/project/build.properties

@@ -0,0 +1 @@
+sbt.version=0.13.0

+ 8 - 0
frameworks/Scala/play2-scala/play2-java-ebean/project/plugins.sbt

@@ -0,0 +1,8 @@
+// Comment to get more information during initialization
+logLevel := Level.Warn
+
+// The Typesafe repository 
+resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
+
+// Use the Play sbt plugin for Play projects
+addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.2.0")

+ 9 - 0
frameworks/Scala/play2-scala/play2-java-ebean/source_code

@@ -0,0 +1,9 @@
+./play-java/app/
+./play-java/app/controllers
+./play-java/app/controllers/Application.java
+./play-java/app/utils
+./play-java/app/utils/Predicate.java
+./play-java/app/utils/PredicatedAction.java
+./play-java/app/utils/Predicated.java
+./play-java/app/models
+./play-java/app/models/World.java

+ 30 - 0
frameworks/Scala/play2-scala/play2-java/.gitignore

@@ -0,0 +1,30 @@
+logs
+project/project
+project/target
+target
+tmp
+.history
+dist
+
+# Ignore all dotfiles...
+.*
+# except for .gitignore
+!.gitignore
+
+# Ignore Play! working directory #
+db
+eclipse
+lib
+log
+logs
+modules
+precompiled
+project/project
+project/target
+target
+tmp
+test-result
+server.pid
+*.iml
+*.eml
+

+ 18 - 0
frameworks/Scala/play2-scala/play2-java/README.md

@@ -0,0 +1,18 @@
+#Play Benchmarking Test
+
+This is the Play portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+
+### JSON Encoding Test
+
+* [JSON test source](app/controllers/Application.java)
+
+## Infrastructure Software Versions
+The tests were run with:
+
+* [Java OpenJDK 1.7.0_09](http://openjdk.java.net/)
+* [Play 2](http://http://www.playframework.com/)
+
+## Test URLs
+### JSON Encoding Test
+
+http://localhost/json

+ 19 - 0
frameworks/Scala/play2-scala/play2-java/app/controllers/Application.java

@@ -0,0 +1,19 @@
+package controllers;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import play.mvc.Controller;
+import play.mvc.Result;
+
+public class Application extends Controller {
+
+    //http://stackoverflow.com/questions/3907929/should-i-make-jacksons-objectmapper-as-static-final
+    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
+
+    public static Result json() {
+        final ObjectNode result = OBJECT_MAPPER.createObjectNode();
+        result.put("message", "Hello, World!");
+        return ok(result);
+    }
+
+}

+ 5 - 0
frameworks/Scala/play2-scala/play2-java/build.sbt

@@ -0,0 +1,5 @@
+name := "play2-java"
+
+version := "1.0-SNAPSHOT"
+
+lazy val root = (project in file(".")).enablePlugins(PlayJava)

+ 26 - 0
frameworks/Scala/play2-scala/play2-java/conf/application.conf

@@ -0,0 +1,26 @@
+# This is the main configuration file for the application.
+# ~~~~~
+
+# 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!
+application.secret="RItx1I:80?W@]8GAtPDuF8Ydd3mXM85p/<7og]Q;uBOdijQAauRDgu73B6`wQP59"
+
+# The application languages
+# ~~~~~
+application.langs="en"
+
+# Logger
+# ~~~~~
+# You can also configure logback (http://logback.qos.ch/), by providing a logger.xml file in the conf directory .
+
+# Root logger:
+logger.root=ERROR
+
+# Logger used by the framework:
+logger.play=ERROR
+
+# Logger provided to your application:
+logger.application=ERROR
+

+ 9 - 0
frameworks/Scala/play2-scala/play2-java/conf/routes

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

+ 1 - 0
frameworks/Scala/play2-scala/play2-java/project/build.properties

@@ -0,0 +1 @@
+sbt.version=0.13.5

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

@@ -0,0 +1,8 @@
+// Comment to get more information during initialization
+logLevel := Level.Warn
+
+// The Typesafe repository 
+resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
+
+// Use the Play sbt plugin for Play projects
+addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.2")

+ 9 - 0
frameworks/Scala/play2-scala/play2-java/source_code

@@ -0,0 +1,9 @@
+./play-java/app/
+./play-java/app/controllers
+./play-java/app/controllers/Application.java
+./play-java/app/utils
+./play-java/app/utils/Predicate.java
+./play-java/app/utils/PredicatedAction.java
+./play-java/app/utils/Predicated.java
+./play-java/app/models
+./play-java/app/models/World.java

+ 33 - 0
frameworks/Scala/play2-scala/play2-scala-anorm/.gitignore

@@ -0,0 +1,33 @@
+logs
+project/project
+project/target
+public
+target
+test
+tmp
+.history
+dist
+conf/evolutions
+
+# Ignore all dotfiles...
+.*
+# except for .gitignore
+!.gitignore
+
+# Ignore Play! working directory #
+db
+eclipse
+lib
+log
+logs
+modules
+precompiled
+project/project
+project/target
+target
+tmp
+test-result
+server.pid
+*.iml
+*.eml
+

+ 20 - 0
frameworks/Scala/play2-scala/play2-scala-anorm/README.md

@@ -0,0 +1,20 @@
+#Play Benchmarking Test
+
+This is the Play portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+
+### Data-Store/Database Mapping Test
+
+* [Database test controller](app/controllers/Application.scala)
+* [Database test model](app/models/World.scala)
+
+## Infrastructure Software Versions
+The tests were run with:
+
+* [Java OpenJDK 1.7.0_09](http://openjdk.java.net/)
+* [Play 2](http://http://www.playframework.com/)
+
+## Test URLs
+
+### Data-Store/Database Mapping Test
+
+http://localhost/db?queries=5

+ 106 - 0
frameworks/Scala/play2-scala/play2-scala-anorm/app/controllers/Application.scala

@@ -0,0 +1,106 @@
+package controllers
+
+import play.api.Play.current
+import play.api.db.DB
+import play.api.mvc._
+import play.api.libs.json.Json
+import java.util.concurrent._
+import scala.concurrent._
+import models.{World, Fortune}
+import utils._
+import scala.concurrent.Future
+
+import play.api.libs.concurrent.Execution.Implicits._
+import play.core.NamedThreadFactory
+
+object Application extends Controller {
+
+  private val TestDatabaseRows = 10000
+
+  private val partitionCount = current.configuration.getInt("db.default.partitionCount").getOrElse(2)
+  private val maxConnections =
+    partitionCount * current.configuration.getInt("db.default.maxConnectionsPerPartition").getOrElse(5)
+  private val minConnections =
+    partitionCount * current.configuration.getInt("db.default.minConnectionsPerPartition").getOrElse(5)
+
+  private val tpe = new ThreadPoolExecutor(minConnections, maxConnections,
+    0L, TimeUnit.MILLISECONDS,
+    new LinkedBlockingQueue[Runnable](),
+    new NamedThreadFactory("dbEc"))
+  private val dbEc = ExecutionContext.fromExecutorService(tpe)
+
+  // 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.
+  def isDbQueueTooBig: Boolean = tpe.getQueue.size() <= 1024
+
+  def db = PredicatedAction(isDbQueueTooBig, ServiceUnavailable) {
+    Action.async {
+      getRandomWorlds(1).map { worlds =>
+        Ok(Json.toJson(worlds.head))
+      }
+    }
+  }
+
+  def queries(countString: String) = PredicatedAction(isDbQueueTooBig, ServiceUnavailable) {
+    Action.async {
+      val n = parseCount(countString)
+      getRandomWorlds(n).map { worlds =>
+        Ok(Json.toJson(worlds))
+      }
+    }
+  }
+
+  private def parseCount(s: String): Int = {
+    try {
+      val parsed = java.lang.Integer.parseInt(s, 10)
+      parsed match {
+        case i if i < 1 => 1
+        case i if i > 500 => 500
+        case i => i
+      }
+    } catch {
+      case _: NumberFormatException => 1
+    }
+  }
+
+  private def getRandomWorlds(n: Int): Future[Seq[World]] = Future {
+    val random = ThreadLocalRandom.current()
+    DB.withConnection { implicit connection =>
+      for (_ <- 1 to n) yield {
+        val randomId: Long = random.nextInt(TestDatabaseRows) + 1
+        World.findById(randomId)
+      }
+    }
+  }(dbEc)
+
+  def fortunes() = PredicatedAction(isDbQueueTooBig, ServiceUnavailable) {
+    Action.async {
+      Future {
+        val fortunes = Fortune.getAll()
+        val extendedFortunes = Fortune(0.toLong, "Additional fortune added at request time.") +: fortunes
+        Ok(views.html.fortune(extendedFortunes))
+      }
+    }
+  }
+
+  def update(countString: String) = PredicatedAction(isDbQueueTooBig, ServiceUnavailable) {
+    Action.async {
+      val n = parseCount(countString)
+      Future {
+        val random = ThreadLocalRandom.current()
+        val worlds = DB.withConnection { implicit connection =>
+          for(_ <- 1 to n) yield {
+            val randomId: Long = random.nextInt(TestDatabaseRows) + 1
+            val world = World.findById(random.nextInt(TestDatabaseRows) + 1)
+            val updatedWorld = world.copy(randomNumber = random.nextInt(10000) + 1)
+            World.updateRandom(updatedWorld)
+            updatedWorld
+          }
+        }
+        Ok(Json.toJson(worlds)).withHeaders("Server" -> "Netty")
+      }(dbEc)
+    }
+  }
+}

+ 25 - 0
frameworks/Scala/play2-scala/play2-scala-anorm/app/models/Fortune.scala

@@ -0,0 +1,25 @@
+package models
+
+import play.api.db._
+import play.api.Play.current
+import anorm._
+import anorm.SqlParser._
+import scala.language.postfixOps
+
+case class Fortune(id: Long, message: String)
+
+object Fortune {
+
+  val simpleRowParser = {
+    get[Long]("fortune.id") ~
+    get[String]("fortune.message") map {
+      case id~message => Fortune(id, message)
+    }
+  }
+
+  def getAll(): List[Fortune] = {
+    DB.withConnection { implicit connection =>
+      SQL("SELECT * FROM Fortune").as(Fortune.simpleRowParser *)
+    }
+  }
+}

+ 55 - 0
frameworks/Scala/play2-scala/play2-scala-anorm/app/models/World.scala

@@ -0,0 +1,55 @@
+package models
+
+import anorm._
+import anorm.SqlParser._
+import java.sql.Connection
+import play.api.db._
+import play.api.libs.functional.syntax._
+import play.api.libs.json._
+import play.api.Play.current
+
+case class World(id: Pk[Long], randomNumber: Long)
+
+object World {
+    /**
+    * Convert a World to Json object
+    */
+  implicit val toJson = new Writes[World] {
+    def writes(w: World): JsValue = {
+      Json.obj(
+        "id" -> w.id.get,
+        "randomNumber" -> w.randomNumber
+      )
+    }
+  }
+
+  /**
+   * Parse a World from a ResultSet
+   */
+  val simpleRowParser = {
+    get[Pk[Long]]("world.id") ~
+    get[Long]("world.randomNumber") map {
+      case id~randomNumber => World(id, randomNumber)
+    }
+  }
+
+  /**
+   * Retrieve a World by id.
+   */
+  def findById(id: Long)(implicit connection: Connection): World = {
+    DB.withConnection { implicit connection =>
+      SQL("SELECT * FROM World WHERE id = {id}").on(
+          "id" -> id
+      ).as(World.simpleRowParser.single)
+    }
+  }
+
+  def updateRandom(world: World)(implicit connection: Connection) {
+    DB.withConnection { implicit connection =>
+      SQL("UPDATE World SET randomNumber = {randomNumber} WHERE id = {id}").on(
+        "id" -> world.id.get,
+        "randomNumber" -> world.randomNumber
+      ).executeUpdate()
+    }
+  }
+}

+ 20 - 0
frameworks/Scala/play2-scala/play2-scala-anorm/app/utils/PredicatedAction.scala

@@ -0,0 +1,20 @@
+package utils
+
+import play.api.mvc._
+import scala.concurrent.{Promise, Future}
+
+/**
+ * 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.
+ */
+class PredicatedActionBuilder {
+  def apply[A](p: => Boolean, failed: => SimpleResult)(action: Action[A]): Action[A] = new Action[A] {
+    def apply(request: Request[A]): Future[SimpleResult] = {
+      if (p) action(request) else Promise.successful(failed).future
+    }
+
+    lazy val parser = action.parser
+  }
+}
+
+object PredicatedAction extends PredicatedActionBuilder

+ 18 - 0
frameworks/Scala/play2-scala/play2-scala-anorm/app/views/fortune.scala.html

@@ -0,0 +1,18 @@
+@(fortunes: List[Fortune])
+
+@main("Fortunes") {
+    <table>
+        <tr>
+            <th>id</th>
+            <th>message</th>
+        </tr>
+
+        @fortunes.sortBy(_.message).map { case Fortune(id, message) =>
+            <tr>
+                <td>@id</td>
+                <td>@message</td>
+            </tr>
+        }
+
+    </table>
+}

+ 12 - 0
frameworks/Scala/play2-scala/play2-scala-anorm/app/views/main.scala.html

@@ -0,0 +1,12 @@
+@(title: String)(content: Html)
+
+<!DOCTYPE html>
+
+<html>
+<head>
+    <title>@title</title>
+</head>
+<body>
+    @content
+</body>
+</html>

+ 9 - 0
frameworks/Scala/play2-scala/play2-scala-anorm/build.sbt

@@ -0,0 +1,9 @@
+name := "play2-scala-anorm"
+
+version := "1.0-SNAPSHOT"
+
+libraryDependencies ++= Seq(jdbc, anorm, "mysql" % "mysql-connector-java" % "5.1.22")
+
+dependencyOverrides += "com.jolbox" % "bonecp" % "0.7.1.RELEASE"
+
+playScalaSettings

+ 66 - 0
frameworks/Scala/play2-scala/play2-scala-anorm/conf/application.conf

@@ -0,0 +1,66 @@
+# This is the main configuration file for the application.
+# ~~~~~
+
+# 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!
+application.secret="RItx1I:80?W@]8GAtPDuF8Ydd3mXM85p/<7og]Q;uBOdijQAauRDgu73B6`wQP59"
+
+# The application languages
+# ~~~~~
+application.langs="en"
+
+# Global object class
+# ~~~~~
+# Define the Global object class for this application.
+# Default to Global in the root package.
+# global=Global
+
+# 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://!!DATABASE_HOST!!: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.user=benchmarkdbuser
+db.default.password=benchmarkdbpass
+db.default.jndiName=DefaultDS
+
+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. 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.default.maxConnectionsPerPartition=64
+
+# The number of initial connections, per partition.
+db.default.minConnectionsPerPartition=64
+
+# Evolutions
+# ~~~~~
+# You can disable evolutions if needed
+# evolutionplugin=disabled
+
+# Logger
+# ~~~~~
+# You can also configure logback (http://logback.qos.ch/), by providing a logger.xml file in the conf directory .
+
+# Root logger:
+logger.root=ERROR
+
+# Logger used by the framework:
+logger.play=ERROR
+
+# Logger provided to your application:
+logger.application=ERROR

+ 12 - 0
frameworks/Scala/play2-scala/play2-scala-anorm/conf/routes

@@ -0,0 +1,12 @@
+# Routes
+# 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     /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)

+ 1 - 0
frameworks/Scala/play2-scala/play2-scala-anorm/project/build.properties

@@ -0,0 +1 @@
+sbt.version=0.13.0

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

@@ -0,0 +1,8 @@
+// Comment to get more information during initialization
+logLevel := Level.Warn
+
+// The Typesafe repository 
+resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
+
+// Use the Play sbt plugin for Play projects
+addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.2.0")

+ 11 - 0
frameworks/Scala/play2-scala/play2-scala-anorm/source_code

@@ -0,0 +1,11 @@
+./play-scala/app/
+./play-scala/app/controllers
+./play-scala/app/controllers/Application.scala
+./play-scala/app/views
+./play-scala/app/views/main.scala.html
+./play-scala/app/views/fortune.scala.html
+./play-scala/app/utils
+./play-scala/app/utils/PredicatedAction.scala
+./play-scala/app/models
+./play-scala/app/models/Fortune.scala
+./play-scala/app/models/World.scala

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