Browse Source

Merge pull request #2525 from greenlaw110/actframework

Add Actframework benchmark set
Mike Smith 8 years ago
parent
commit
89bef39b37
35 changed files with 1430 additions and 0 deletions
  1. 1 0
      .travis.yml
  2. 18 0
      frameworks/Java/act/.gitignore
  3. 435 0
      frameworks/Java/act/README.md
  4. 91 0
      frameworks/Java/act/benchmark_config.json
  5. 15 0
      frameworks/Java/act/pipeline.lua
  6. 134 0
      frameworks/Java/act/pom.xml
  7. 6 0
      frameworks/Java/act/run.sh
  8. 24 0
      frameworks/Java/act/setup.sh
  9. 28 0
      frameworks/Java/act/source_code
  10. 66 0
      frameworks/Java/act/src/assembly/pkg.xml
  11. 41 0
      frameworks/Java/act/src/main/java/com/techempower/act/AppEntry.java
  12. 32 0
      frameworks/Java/act/src/main/java/com/techempower/act/controller/FortuneControllerBase.java
  13. 83 0
      frameworks/Java/act/src/main/java/com/techempower/act/controller/WorldControllerBase.java
  14. 17 0
      frameworks/Java/act/src/main/java/com/techempower/act/domain/IFortune.java
  15. 11 0
      frameworks/Java/act/src/main/java/com/techempower/act/domain/IWorld.java
  16. 20 0
      frameworks/Java/act/src/main/java/com/techempower/act/mongo/controller/FortuneController.java
  17. 24 0
      frameworks/Java/act/src/main/java/com/techempower/act/mongo/controller/WorldController.java
  18. 35 0
      frameworks/Java/act/src/main/java/com/techempower/act/mongo/domain/Fortune.java
  19. 33 0
      frameworks/Java/act/src/main/java/com/techempower/act/mongo/domain/World.java
  20. 16 0
      frameworks/Java/act/src/main/java/com/techempower/act/mysql/controller/FortuneController.java
  21. 17 0
      frameworks/Java/act/src/main/java/com/techempower/act/mysql/controller/WorldController.java
  22. 18 0
      frameworks/Java/act/src/main/java/com/techempower/act/mysql/domain/Fortune.java
  23. 17 0
      frameworks/Java/act/src/main/java/com/techempower/act/mysql/domain/World.java
  24. 16 0
      frameworks/Java/act/src/main/java/com/techempower/act/pgsql/controller/FortuneController.java
  25. 17 0
      frameworks/Java/act/src/main/java/com/techempower/act/pgsql/controller/WorldController.java
  26. 18 0
      frameworks/Java/act/src/main/java/com/techempower/act/pgsql/domain/Fortune.java
  27. 17 0
      frameworks/Java/act/src/main/java/com/techempower/act/pgsql/domain/World.java
  28. 25 0
      frameworks/Java/act/src/main/java/com/techempower/act/sql/controller/SqlWorldControllerBase.java
  29. 32 0
      frameworks/Java/act/src/main/java/com/techempower/act/sql/domain/Fortune.java
  30. 40 0
      frameworks/Java/act/src/main/java/com/techempower/act/sql/domain/World.java
  31. 11 0
      frameworks/Java/act/src/main/resources/conf/common/app.properties
  32. 24 0
      frameworks/Java/act/src/main/resources/conf/common/db.properties
  33. 26 0
      frameworks/Java/act/src/main/resources/logback.xml
  34. 1 0
      frameworks/Java/act/src/main/resources/routes.conf
  35. 21 0
      frameworks/Java/act/src/main/resources/rythm/fortunes.html

+ 1 - 0
.travis.yml

@@ -67,6 +67,7 @@ env:
     - "TESTDIR=Haskell/yesod"
     - "TESTDIR=Haskell/servant"
     - "TESTDIR=Haskell/spock"
+    - "TESTDIR=Java/act"
     - "TESTDIR=Java/activeweb"
     - "TESTDIR=Java/baratine"
     - "TESTDIR=Java/bayou"

+ 18 - 0
frameworks/Java/act/.gitignore

@@ -0,0 +1,18 @@
+*.class
+.classpath
+.project
+.settings
+.vscode
+# Package Files #
+*.jar
+*.war
+*.ear
+lib
+target
+.idea
+classes
+*.iml
+deploy
+**/.act*
+git.log
+

+ 435 - 0
frameworks/Java/act/README.md

@@ -0,0 +1,435 @@
+# ActFramework Benchmarking Test
+
+This is the ActFramework portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+
+This is using [ActFramework](http://actframework.org) to build an application.
+
+## How to run this app locally
+
+You can easily run this sample application with mongodb and mysql, postgresql setup correctly.
+For that, type:
+
+```
+mvn clean package
+cd target/dist
+unzip *.zip
+./start
+```
+
+Or simply run `run.sh`
+    
+
+## Application Endpoints
+
+### JSON serialization
+
+* http://localhost:8080/json
+
+### Single database query
+
+* `mongo`: http://localhost:8080/mongo/db
+* `mysql`: http://localhost:8080/mysql/db
+* `pgsql`: http://localhost:8080/pgsql/db
+
+### Multiple queries
+
+* `mongo`: http://localhost:8080/mongo/queries?quries=20
+* `mysql`: http://localhost:8080/mysql/queries?quries=20
+* `pgsql`: http://localhost:8080/pgsql/queries?quries=20
+
+### Fortunes
+
+* `mongo`: http://localhost:8080/mongo/fortunes
+* `mysql`: http://localhost:8080/mysql/fortunes
+* `pgsql`: http://localhost:8080/pgsql/fortunes
+
+### DB updates
+
+* `mongo`: http://localhost:8080/mongo/updates?quries=20
+* `mysql`: http://localhost:8080/mysql/updates?quries=20
+* `pgsql`: http://localhost:8080/pgsql/updates?quries=20
+
+### Plain text
+
+* mongo: http://localhost:8080/plaintext
+
+## Source code
+
+### App entry and non-database request handlers
+
+* [App entry](src/main/java/com/techempower/act/AppEntry.java)
+* [json and plaintext handler](src/main/java/com/techempower/act/controller/HelloController.java)
+
+### Database relevant source files
+
+This application is organized to support access three database sources: `mongo`, `mysql`, `pgsql`. 
+However most of the logic is the same when handling request sent to different data sources. We have
+organized the project in a way to maximize the reuse of coding for the same logic. Each piece of source
+unit are put into four groups: 
+
+* `common`: encapsulate the common logic or data models
+* `mongo` : the mongodb adaptor
+* `mysql` : the mysql adaptor
+* `pgsql` : the postgresql adaptor
+
+#### Domain Models
+
+##### Common
+
+* [Fortune](src/main/java/com/techempower/act/domain/IFortune.java)
+* [World](src/main/java/com/techempower/act/domain/IWorld.java)
+
+##### Mongo
+
+* [Fortune](src/main/java/com/techempower/act/mongo/domain/Fortune.java)
+* [World](src/main/java/com/techempower/act/mongo/domain/World.java)
+
+##### SQL Common 
+
+The common base classes for mysql and pgsql classes
+
+* [Fortune](src/main/java/com/techempower/act/sql/domain/Fortune.java)
+* [World](src/main/java/com/techempower/act/sql/domain/World.java)
+
+##### MySQL
+
+* [Fortune](src/main/java/com/techempower/act/mysql/domain/Fortune.java)
+* [World](src/main/java/com/techempower/act/mysql/domain/World.java)
+
+##### Postgresql
+
+* [Fortune](src/main/java/com/techempower/act/pgsql/domain/Fortune.java)
+* [World](src/main/java/com/techempower/act/pgsql/domain/World.java)
+
+#### Controllers
+
+##### Common
+
+* [Fortune controller](src/main/java/com/techempower/act/controller/FortuneControllerBase.java) - for `fortunes` endpoint
+* [World controller](src/main/java/com/techempower/act/controller/WorldControllerBase.java) - for `db`, `queries` and `updates` endpoint
+
+##### Mongo
+
+* [Fortune controller](src/main/java/com/techempower/act/mongo/controller/FortuneController.java) - for `/mongo/fortunes` endpoint
+* [World controller](src/main/java/com/techempower/act/mongo/controller/WorldController.java) - for `/mongo/db`, `/mongo/queries` and `/mongo/updates` endpoint
+
+##### SQL Common
+
+The common base classes for mysql and pgsql classes
+
+* [Fortune controller](src/main/java/com/techempower/act/sql/controller/FortuneController.java) 
+* [World controller](src/main/java/com/techempower/act/sql/controller/WorldController.java) 
+
+
+##### MySQL
+
+* [Fortune controller](src/main/java/com/techempower/act/mysql/controller/FortuneController.java) - for `/mysql/fortunes` endpoint
+* [World controller](src/main/java/com/techempower/act/mysql/controller/WorldController.java) - for `/mysql/db`, `/mysql/queries` and `/mysql/updates` endpoint
+
+##### Postgresql
+
+* [Fortune controller](src/main/java/com/techempower/act/pgsql/controller/FortuneController.java) - for `/pgsql/fortunes` endpoint
+* [World controller](src/main/java/com/techempower/act/pgsql/controller/WorldController.java) - for `/pgsql/db`, `/pgsql/queries` and `/pgsql/updates` endpoint
+
+
+
+## Infrastructure Software Versions
+The tests were run with:
+
+* [ActFramework 0.4.0-SNAPSHOT](http://actframework.org/)
+* [act-ebean plugin 0.4.0-SNAPSHOT](https://github.com/actframework/act-ebean)
+* [act-morphia plugin 0.5.0-SNAPSHOT](https://github.com/actframework/act-morphia)
+* [Undertow 1.4.8.Final](http://undertow.io/)
+
+
+## Local Test Result
+
+|            Test            | Throughput |  Latency  | Timeout |
+| -------------------------- | ---------: | --------: | ------: |
+| json                       |  828527.50 |    4.43ms |         |
+| single query - mongo       |   44575.49 |   15.12ms |         |
+| single query - mysql       |   25300.02 |   55.57ms |         |
+| single query - pgsql       |   36930.28 |   48.51ms |         |
+| 20 queries - mongo         |    2655.75 |  107.18ms |         |
+| 20 queries - mysql         |    1225.00 |       n/a |     768 |
+| 20 queries - pgsql         |    2010.60 |  386.54ms |      22 |
+| fortunes - mongo           |   22417.17 |   48.37ms |         |
+| fortunes - mysql           |   22326.85 |   47.14ms |         |
+| fortunes - pgsql           |   24216.44 |   85.19ms |         |
+| 20 updates - mongo         |    2250.82 |  562.06ms |         |
+| 20 updates - mysql         |     408.33 |       n/a |     256 |
+| 20 updates - pgsql         |     707.77 |       n/a |     444 |
+| plaintext                  | 1361223.78 |    2.36ms |         |
+
+
+### Local Test Logs
+
+#### JSON Serialization
+
+```
+luog@luog-Satellite-P50-A:~/p/greenlaw110/webframework-benchmark$ wrk -t4 -c256 -d10s http://localhost:8080 -s pipeline.lua --latency -- /json 16
+Running 10s test @ http://localhost:8080
+  4 threads and 256 connections
+  Thread Stats   Avg      Stdev     Max   +/- Stdev
+    Latency     4.43ms    4.34ms 202.38ms   90.32%
+    Req/Sec   209.33k    59.03k  389.44k    62.25%
+  Latency Distribution
+     50%    3.70ms
+     75%    6.09ms
+     90%    8.69ms
+     99%   15.91ms
+  8359840 requests in 10.09s, 1.34GB read
+Requests/sec: 828527.50
+Transfer/sec:    135.91MB
+```
+
+#### Plain text
+
+```
+luog@luog-Satellite-P50-A:~/p/greenlaw110/webframework-benchmark$ wrk -t4 -c256 -d10s http://localhost:8080 -s pipeline.lua --latency -- /plaintext 16
+Running 10s test @ http://localhost:8080
+  4 threads and 256 connections
+  Thread Stats   Avg      Stdev     Max   +/- Stdev
+    Latency     2.36ms    2.08ms  39.37ms   85.72%
+    Req/Sec   344.48k    82.82k  691.36k    66.25%
+  Latency Distribution
+     50%    1.89ms
+     75%    3.16ms
+     90%    4.58ms
+     99%   10.10ms
+  13751216 requests in 10.10s, 1.95GB read
+Requests/sec: 1361223.78
+Transfer/sec:    197.32MB
+```
+
+#### Single Query - MongoDB
+
+```
+luog@luog-Satellite-P50-A:~/p/greenlaw110/webframework-benchmark$ wrk -t4 -c256 -d10s http://localhost:8080 -s pipeline.lua --latency -- /mongo/db 16
+Running 10s test @ http://localhost:8080
+  4 threads and 256 connections
+  Thread Stats   Avg      Stdev     Max   +/- Stdev
+    Latency    15.12ms   30.09ms 126.68ms    0.00%
+    Req/Sec    11.23k   657.00    13.74k    67.75%
+  Latency Distribution
+     50%    0.00us
+     75%    0.00us
+     90%    0.00us
+     99%    0.00us
+  447408 requests in 10.04s, 75.00MB read
+Requests/sec:  44575.49
+Transfer/sec:      7.47MB
+```
+
+#### Single query - MySQL
+
+```
+luog@luog-Satellite-P50-A:~/p/greenlaw110/webframework-benchmark$ wrk -t4 -c256 -d10s http://localhost:8080 -s pipeline.lua --latency -- /mysql/db 16
+Running 10s test @ http://localhost:8080
+  4 threads and 256 connections
+  Thread Stats   Avg      Stdev     Max   +/- Stdev
+    Latency    55.57ms   50.98ms 326.24ms    5.78%
+    Req/Sec     6.39k     1.07k   10.34k    78.09%
+  Latency Distribution
+     50%    0.00us
+     75%    0.00us
+     90%    0.00us
+     99%    0.00us
+  253872 requests in 10.03s, 42.56MB read
+Requests/sec:  25300.02
+Transfer/sec:      4.24MB
+```
+
+#### Single query - Postgres
+
+```
+luog@luog-Satellite-P50-A:~/p/greenlaw110/webframework-benchmark$ wrk -t4 -c256 -d10s http://localhost:8080 -s pipeline.lua --latency -- /pgsql/db 16
+Running 10s test @ http://localhost:8080
+  4 threads and 256 connections
+  Thread Stats   Avg      Stdev     Max   +/- Stdev
+    Latency    48.51ms   32.12ms 335.31ms   28.60%
+    Req/Sec     9.33k     0.93k   12.61k    89.67%
+  Latency Distribution
+     50%  109.70ms
+     75%    0.00us
+     90%    0.00us
+     99%    0.00us
+  370144 requests in 10.02s, 62.05MB read
+Requests/sec:  36930.28
+Transfer/sec:      6.19MB
+```
+
+#### 20 queries - Mongo
+
+```
+luog@luog-Satellite-P50-A:~/p/greenlaw110/webframework-benchmark$ wrk -t4 -c256 -d10s http://localhost:8080 -s pipeline.lua --latency -- /mongo/queries?queries=20 16
+Running 10s test @ http://localhost:8080
+  4 threads and 256 connections
+  Thread Stats   Avg      Stdev     Max   +/- Stdev
+    Latency   107.18ms  361.87ms   1.52s     0.00%
+    Req/Sec     2.07k     2.81k    8.96k    82.14%
+  Latency Distribution
+     50%    0.00us
+     75%    0.00us
+     90%    0.00us
+     99%    0.00us
+  26720 requests in 10.06s, 19.94MB read
+Requests/sec:   2655.75
+Transfer/sec:      1.98MB
+```
+
+#### 20 queries - MySQL
+
+```
+luog@luog-Satellite-P50-A:~/p/greenlaw110/webframework-benchmark$ wrk -t4 -c256 -d10s http://localhost:8080 -s pipeline.lua --latency -- /mysql/queries?queries=20 16
+Running 10s test @ http://localhost:8080
+  4 threads and 256 connections
+  Thread Stats   Avg      Stdev     Max   +/- Stdev
+    Latency     0.00us    0.00us   0.00us    -nan%
+    Req/Sec     1.76k     1.97k    5.82k    78.69%
+  Latency Distribution
+     50%    0.00us
+     75%    0.00us
+     90%    0.00us
+     99%    0.00us
+  12288 requests in 10.03s, 9.17MB read
+  Socket errors: connect 0, read 0, write 0, timeout 768
+Requests/sec:   1225.00
+Transfer/sec:      0.91MB
+```
+
+#### 20 queries - Postgres
+ 
+```
+luog@luog-Satellite-P50-A:~/p/greenlaw110/webframework-benchmark$ wrk -t4 -c256 -d10s http://localhost:8080 -s pipeline.lua --latency -- /pgsql/queries?queries=20 16
+Running 10s test @ http://localhost:8080
+  4 threads and 256 connections
+  Thread Stats   Avg      Stdev     Max   +/- Stdev
+    Latency   386.54ms  624.21ms   2.00s     0.00%
+    Req/Sec     1.10k     1.14k    4.36k    82.18%
+  Latency Distribution
+     50%    0.00us
+     75%    0.00us
+     90%    0.00us
+     99%    0.00us
+  20208 requests in 10.05s, 15.08MB read
+  Socket errors: connect 0, read 0, write 0, timeout 22
+Requests/sec:   2010.60
+Transfer/sec:      1.50MB
+```
+
+#### 20 updates - Mongo
+
+```
+luog@luog-Satellite-P50-A:~/p/greenlaw110/webframework-benchmark$ wrk -t4 -c256 -d10s http://localhost:8080 -s pipeline.lua --latency -- /mongo/updates?queries=20 16
+Running 10s test @ http://localhost:8080
+  4 threads and 256 connections
+  Thread Stats   Avg      Stdev     Max   +/- Stdev
+    Latency   562.06ms  567.30ms   1.98s     1.11%
+    Req/Sec     1.57k     1.62k    7.43k    80.83%
+  Latency Distribution
+     50%    0.00us
+     75%    0.00us
+     90%    0.00us
+     99%    0.00us
+  22624 requests in 10.05s, 16.89MB read
+Requests/sec:   2250.82
+Transfer/sec:      1.68MB
+```
+
+#### 20 updates - MySQL
+
+```
+luog@luog-Satellite-P50-A:~/p/greenlaw110/webframework-benchmark$ wrk -t4 -c256 -d10s http://localhost:8080 -s pipeline.lua --latency -- /mysql/updates?queries=20 16
+Running 10s test @ http://localhost:8080
+  4 threads and 256 connections
+  Thread Stats   Avg      Stdev     Max   +/- Stdev
+    Latency     0.00us    0.00us   0.00us    -nan%
+    Req/Sec     1.06k     1.02k    3.39k    64.52%
+  Latency Distribution
+     50%    0.00us
+     75%    0.00us
+     90%    0.00us
+     99%    0.00us
+  4096 requests in 10.03s, 3.06MB read
+  Socket errors: connect 0, read 0, write 0, timeout 256
+Requests/sec:    408.33
+Transfer/sec:    312.06KB
+```
+
+#### 20 updates - Postgresql
+
+```
+luog@luog-Satellite-P50-A:~/p/greenlaw110/webframework-benchmark$ wrk -t4 -c256 -d10s http://localhost:8080 -s pipeline.lua --latency -- /pgsql/updates?queries=20 16
+Running 10s test @ http://localhost:8080
+  4 threads and 256 connections
+  Thread Stats   Avg      Stdev     Max   +/- Stdev
+    Latency     0.00us    0.00us   0.00us    -nan%
+    Req/Sec     1.21k     1.28k    4.80k    84.78%
+  Latency Distribution
+     50%    0.00us
+     75%    0.00us
+     90%    0.00us
+     99%    0.00us
+  7104 requests in 10.04s, 5.30MB read
+  Socket errors: connect 0, read 0, write 0, timeout 444
+Requests/sec:    707.77
+Transfer/sec:    540.90KB
+```
+
+#### Fortunes - Mongo
+
+```
+luog@luog-Satellite-P50-A:~/p/greenlaw110/webframework-benchmark$ wrk -t4 -c256 -d10s http://localhost:8080 -s pipeline.lua --latency -- /mongo/fortunes 16
+Running 10s test @ http://localhost:8080
+  4 threads and 256 connections
+  Thread Stats   Avg      Stdev     Max   +/- Stdev
+    Latency    48.37ms   62.79ms 283.94ms    0.00%
+    Req/Sec     5.66k     1.15k   10.08k    77.02%
+  Latency Distribution
+     50%    0.00us
+     75%    0.00us
+     90%    0.00us
+     99%    0.00us
+  224908 requests in 10.03s, 313.15MB read
+Requests/sec:  22417.17
+Transfer/sec:     31.21MB
+```
+
+#### Fortunes - MySQL
+
+```
+luog@luog-Satellite-P50-A:~/p/greenlaw110/webframework-benchmark$ wrk -t4 -c256 -d10s http://localhost:8080 -s pipeline.lua --latency -- /mysql/fortunes 16
+Running 10s test @ http://localhost:8080
+  4 threads and 256 connections
+  Thread Stats   Avg      Stdev     Max   +/- Stdev
+    Latency    47.14ms   62.73ms 291.87ms    0.00%
+    Req/Sec     5.64k     1.34k    9.76k    73.43%
+  Latency Distribution
+     50%    0.00us
+     75%    0.00us
+     90%    0.00us
+     99%    0.00us
+  224776 requests in 10.07s, 312.97MB read
+Requests/sec:  22326.85
+Transfer/sec:     31.09MB
+```
+
+#### Fortunes - Postgresql
+
+```
+luog@luog-Satellite-P50-A:~/p/greenlaw110/FrameworkBenchmarks/frameworks/Java/act$ wrk -t4 -c256 -d10s http://localhost:8080 -s pipeline.lua --latency -- /pgsql/fortunes 16
+Running 10s test @ http://localhost:8080
+  4 threads and 256 connections
+  Thread Stats   Avg      Stdev     Max   +/- Stdev
+    Latency    85.19ms   40.72ms 378.41ms   50.28%
+    Req/Sec     6.26k     1.75k   13.66k    86.67%
+  Latency Distribution
+     50%  123.14ms
+     75%  169.66ms
+     90%    0.00us
+     99%    0.00us
+  242972 requests in 10.03s, 338.31MB read
+Requests/sec:  24216.44
+Transfer/sec:     33.72MB
+```

+ 91 - 0
frameworks/Java/act/benchmark_config.json

@@ -0,0 +1,91 @@
+{
+  "framework": "actframework",
+  "tests": [{
+      "default": {
+      "setup_file": "setup",
+      "json_url": "/json",
+      "plaintext_url": "/plaintext",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "None",
+      "framework": "actframework",
+      "language": "Java",
+      "flavor": "None",
+      "orm": "Full",
+      "platform": "Undertow",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "actframework",
+      "notes": "",
+      "versus": "undertow"
+    },
+    "pgsql": {
+      "setup_file": "setup",
+      "db_url": "/pgsql/db",
+      "query_url": "/pgsql/queries?queries=",
+      "fortune_url": "/pgsql/fortunes",
+      "update_url": "/pgsql/updates?queries=",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "Postgres",
+      "framework": "actframework",
+      "language": "Java",
+      "flavor": "None",
+      "orm": "Full",
+      "platform": "Undertow",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "actframework-pgsql",
+      "notes": "",
+      "versus": "undertow"
+    },
+    "mysql": {
+      "setup_file": "setup",
+      "db_url": "/mysql/db",
+      "query_url": "/mysql/queries?queries=",
+      "fortune_url": "/mysql/fortunes",
+      "update_url": "/mysql/updates?queries=",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "MySQL",
+      "framework": "actframework",
+      "language": "Java",
+      "flavor": "None",
+      "orm": "Full",
+      "platform": "Undertow",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "actframework-mysql",
+      "notes": "",
+      "versus": "undertow"
+    },
+    "mongodb": {
+      "setup_file": "setup",
+      "db_url": "/mongo/db",
+      "query_url": "/mongo/queries?queries=",
+      "fortune_url": "/mongo/fortunes",
+      "update_url": "/mongo/updates?queries=",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "MongoDB",
+      "framework": "actframework",
+      "language": "Java",
+      "flavor": "None",
+      "orm": "Full",
+      "platform": "Undertow",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "actframework-mongo",
+      "notes": "",
+      "versus": "undertow"
+    }
+  }]
+}

+ 15 - 0
frameworks/Java/act/pipeline.lua

@@ -0,0 +1,15 @@
+init = function(args)
+   request_uri = args[1]
+   depth = tonumber(args[2]) or 1
+
+   local r = {}
+   for i=1,depth do
+     r[i] = wrk.format(nil, request_uri)
+   end
+   req = table.concat(r)
+end
+
+request = function()
+   wrk.headers["J-Tenant-Id"] = "1007"
+   return req
+end

+ 134 - 0
frameworks/Java/act/pom.xml

@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xmlns="http://maven.apache.org/POM/4.0.0"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.sonatype.oss</groupId>
+        <artifactId>oss-parent</artifactId>
+        <version>7</version>
+    </parent>
+
+    <groupId>com.techempower</groupId>
+    <artifactId>actframework</artifactId>
+    <version>1.0.0-SNAPSHOT</version>
+    <name>ActFramework sample project</name>
+    <packaging>jar</packaging>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+        <act.version>0.4.0-SNAPSHOT</act.version>
+        <act-morphia.version>0.5.0-SNAPSHOT</act-morphia.version>
+        <act-ebean.version>0.4.0-SNAPSHOT</act-ebean.version>
+        <mysql.version>5.1.38</mysql.version>
+        <postgres-jdbc.version>9.4.1208</postgres-jdbc.version>
+        <app.entry>com.techempower.act.AppEntry</app.entry>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <version>${mysql.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.actframework</groupId>
+            <artifactId>act</artifactId>
+            <version>${act.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.actframework</groupId>
+            <artifactId>act-morphia</artifactId>
+            <version>${act-morphia.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.actframework</groupId>
+            <artifactId>act-ebean</artifactId>
+            <version>${act-ebean.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-classic</artifactId>
+            <version>1.1.6</version>
+        </dependency>
+        <dependency>
+            <groupId>org.postgresql</groupId>
+            <artifactId>postgresql</artifactId>
+            <version>${postgres-jdbc.version}</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <finalName>act</finalName>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+                <filtering>true</filtering>
+            </resource>
+        </resources>
+
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <version>2.5.5</version>
+                <executions>
+                    <execution>
+                        <id>create-archive</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                        <configuration>
+                            <appendAssemblyId>false</appendAssemblyId>
+                            <descriptors>
+                                <descriptor>src/assembly/pkg.xml</descriptor>
+                            </descriptors>
+                            <outputDirectory>${project.build.directory}/dist/</outputDirectory>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+
+        <pluginManagement>
+            <plugins>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-compiler-plugin</artifactId>
+                    <version>3.3</version>
+                    <configuration>
+                        <source>1.8</source>
+                        <target>1.8</target>
+                    </configuration>
+                </plugin>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-source-plugin</artifactId>
+                    <version>2.1.2</version>
+                    <configuration>
+                        <includePom>true</includePom>
+                    </configuration>
+                </plugin>
+                <plugin>
+                    <groupId>org.codehaus.mojo</groupId>
+                    <artifactId>exec-maven-plugin</artifactId>
+                    <version>1.2.1</version>
+                    <configuration>
+                        <executable>java</executable>
+                        <arguments>
+                            <argument>-Xms512m</argument>
+                            <argument>-Xmx512m</argument>
+                            <argument>-classpath</argument>
+                            <classpath/>
+                            <argument>${app.entry}</argument>
+                        </arguments>
+                    </configuration>
+                </plugin>
+            </plugins>
+        </pluginManagement>
+    </build>
+</project>

+ 6 - 0
frameworks/Java/act/run.sh

@@ -0,0 +1,6 @@
+#!/bin/bash
+
+mvn clean package
+cd target/dist
+unzip *.zip
+./start

+ 24 - 0
frameworks/Java/act/setup.sh

@@ -0,0 +1,24 @@
+#!/bin/bash
+
+fw_depends mysql postgresql mongodb java maven
+
+mvn -U clean package
+cd target/dist
+unzip *.zip
+
+
+APP_ENTRY=com.techempower.act.AppEntry
+
+DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
+BASE=$DIR/target/dist
+if [[ $DIR == *"dist" ]]; then
+  BASE=$DIR
+fi
+CP=$BASE/classes:$BASE/lib/*
+echo
+echo CLASSPATH: $CP
+echo
+
+JAVA_OPTS="-Djava.security.egd=file:/dev/./urandom -Dawt.useSystemAAFontSettings=on -server -Xms512m -Xmx2g"
+
+java -server $JAVA_OPTS -Dapp.mode=prod -Dapp.nodeGroup=$GROUP -Dprofile=prod -Dmongo.host=${DBHOST} -Dmysql.host=${DBHOST} -Dpgsql.host=${DBHOST} -cp "$CP" $APP_ENTRY &

+ 28 - 0
frameworks/Java/act/source_code

@@ -0,0 +1,28 @@
+./act/src/main/bin/start
+./act/src/main/java/com/techempower/act/domain/IFortune.java
+./act/src/main/java/com/techempower/act/domain/IWorld.java
+./act/src/main/java/com/techempower/act/pgsql/domain/World.java
+./act/src/main/java/com/techempower/act/pgsql/domain/Fortune.java
+./act/src/main/java/com/techempower/act/pgsql/controller/WorldController.java
+./act/src/main/java/com/techempower/act/pgsql/controller/FortuneController.java
+./act/src/main/java/com/techempower/act/controller/FortuneControllerBase.java
+./act/src/main/java/com/techempower/act/controller/WorldControllerBase.java
+./act/src/main/java/com/techempower/act/controller/HelloController.java
+./act/src/main/java/com/techempower/act/mysql/domain/World.java
+./act/src/main/java/com/techempower/act/mysql/domain/Fortune.java
+./act/src/main/java/com/techempower/act/mysql/controller/WorldController.java
+./act/src/main/java/com/techempower/act/mysql/controller/FortuneController.java
+./act/src/main/java/com/techempower/act/AppEntry.java
+./act/src/main/java/com/techempower/act/mongo/domain/World.java
+./act/src/main/java/com/techempower/act/mongo/domain/Fortune.java
+./act/src/main/java/com/techempower/act/mongo/controller/WorldController.java
+./act/src/main/java/com/techempower/act/mongo/controller/FortuneController.java
+./act/src/main/java/com/techempower/act/sql/domain/World.java
+./act/src/main/java/com/techempower/act/sql/domain/Fortune.java
+./act/src/main/java/com/techempower/act/sql/controller/SqlWorldControllerBase.java
+./act/src/main/resources/conf/prod/app.properties
+./act/src/main/resources/conf/common/app.properties
+./act/src/main/resources/conf/common/db.properties
+./act/src/main/resources/logback.xml
+./act/src/main/resources/rythm/fortunes.html
+./act/src/assembly/pkg.xml

+ 66 - 0
frameworks/Java/act/src/assembly/pkg.xml

@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+
+<assembly>
+  <id>dist</id>
+
+  <formats>
+    <format>zip</format>
+  </formats>
+
+  <includeBaseDirectory>false</includeBaseDirectory>
+
+  <fileSets>
+    <fileSet>
+      <directory>${project.basedir}</directory>
+      <outputDirectory></outputDirectory>
+      <includes>
+        <include>README.md</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>${project.build.directory}</directory>
+      <outputDirectory></outputDirectory>
+      <includes>
+        <include>classes/**</include>
+        <include>asset/**</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>${project.basedir}/src/main/asset</directory>
+      <outputDirectory>asset</outputDirectory>
+    </fileSet>
+    <fileSet>
+      <directory>${project.basedir}/src/main/bin</directory>
+      <outputDirectory></outputDirectory>
+      <includes>
+        <include>start*</include>
+      </includes>
+      <filtered>true</filtered>
+    </fileSet>
+  </fileSets>
+
+  <dependencySets>
+    <dependencySet>
+      <outputDirectory>lib</outputDirectory>
+    </dependencySet>
+  </dependencySets>
+</assembly>

+ 41 - 0
frameworks/Java/act/src/main/java/com/techempower/act/AppEntry.java

@@ -0,0 +1,41 @@
+package com.techempower.act;
+
+
+import act.Act;
+import act.Version;
+import act.boot.app.RunApp;
+import act.job.OnAppStart;
+import com.alibaba.fastjson.JSON;
+import org.osgl.http.H;
+
+public class AppEntry {
+
+	private static final String HELLO_WORLD = "Hello, World!";
+
+	public static final class Message {
+
+		private final String message;
+
+		private Message(String message) {
+			this.message = message;
+		}
+
+		public String getMessage() {
+			return message;
+		}
+
+	}
+
+
+	@OnAppStart
+	public void routing() {
+		Act.get("/json", context -> context.resp()
+				.contentType(H.Format.JSON.contentType())
+				.writeContent(JSON.toJSONString(new Message(HELLO_WORLD))));
+	}
+
+	public static void main(String[] args) throws Exception {
+		RunApp.start("Act Test", Version.appVersion(), AppEntry.class);
+	}
+
+}

+ 32 - 0
frameworks/Java/act/src/main/java/com/techempower/act/controller/FortuneControllerBase.java

@@ -0,0 +1,32 @@
+package com.techempower.act.controller;
+
+import act.controller.Controller;
+import act.db.Dao;
+import com.techempower.act.domain.IFortune;
+import com.techempower.act.mongo.domain.Fortune;
+import org.osgl.$;
+import org.osgl.mvc.annotation.GetAction;
+
+import java.util.Collections;
+import java.util.List;
+
+public abstract class FortuneControllerBase<MODEL_TYPE extends IFortune,
+        QUERY_TYPE extends Dao.Query<MODEL_TYPE, QUERY_TYPE>,
+        DAO_TYPE extends Dao<Integer, MODEL_TYPE, QUERY_TYPE>> extends Controller.Util  {
+
+    private DAO_TYPE fortuneDao;
+
+    public FortuneControllerBase(DAO_TYPE fortuneDao) {
+        this.fortuneDao = $.notNull(fortuneDao);
+    }
+
+    @GetAction("fortunes")
+    public void fortunes() {
+        List<IFortune> fortunes = (List)fortuneDao.findAllAsList();
+        fortunes.add(new Fortune(0, "Additional fortune added at request time."));
+        Collections.sort(fortunes);
+
+        template("fortunes", fortunes);
+    }
+
+}

+ 83 - 0
frameworks/Java/act/src/main/java/com/techempower/act/controller/WorldControllerBase.java

@@ -0,0 +1,83 @@
+package com.techempower.act.controller;
+
+import act.app.conf.AutoConfig;
+import act.controller.Controller;
+import act.db.Dao;
+import com.techempower.act.domain.IWorld;
+import org.osgl.$;
+import org.osgl.mvc.annotation.GetAction;
+import org.osgl.util.Const;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ThreadLocalRandom;
+
+@AutoConfig
+public abstract class WorldControllerBase<MODEL_TYPE extends IWorld,
+		QUERY_TYPE extends Dao.Query<MODEL_TYPE, QUERY_TYPE>,
+		DAO_TYPE extends Dao<Integer, MODEL_TYPE, QUERY_TYPE>> extends Controller.Util {
+
+	/**
+     * This constant will get populated with the value set in
+	 * `app.world.max_row` configuration item
+	 */
+	public static final Const<Integer> WORLD_MAX_ROW = $.constant();
+
+	protected DAO_TYPE worldDao;
+
+	public WorldControllerBase(DAO_TYPE worldDao) {
+		this.worldDao = $.notNull(worldDao);
+	}
+
+	@GetAction("db")
+	public final void singleQuery() {
+		json(findOne());
+	}
+
+	@GetAction("queries")
+	public final void multipleQueries(String queries) {
+		int q = regulateQueries(queries);
+
+		List<MODEL_TYPE> retVal = new ArrayList<>();
+		for (int i = 0; i < q; ++i) {
+			retVal.add(findOne());
+		}
+		json(retVal);
+	}
+
+	@GetAction("updates")
+	public final void updateQueries(String queries) {
+		int q = regulateQueries(queries);
+		List<MODEL_TYPE> retVal = new ArrayList<>();
+		for (int i = 0; i < q; ++i) {
+			retVal.add(findAndModifyOne());
+		}
+		json(retVal);
+	}
+
+	protected final MODEL_TYPE findOne() {
+		return worldDao.findById(randomWorldNumber());
+	}
+
+	protected abstract MODEL_TYPE findAndModifyOne();
+
+	private int regulateQueries(String param) {
+		if (null == param) {
+			return 1;
+		}
+		try {
+			int val = Integer.parseInt(param);
+			if (val < 1) {
+				return 1;
+			}
+			return val > 500 ? 500 : val;
+		} catch (NumberFormatException e) {
+			return 1;
+		}
+	}
+
+	protected final int randomWorldNumber() {
+		return ThreadLocalRandom.current().nextInt(WORLD_MAX_ROW.get()) + 1;
+	}
+
+}

+ 17 - 0
frameworks/Java/act/src/main/java/com/techempower/act/domain/IFortune.java

@@ -0,0 +1,17 @@
+package com.techempower.act.domain;
+
+import act.util.SimpleBean;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * We need this interface because we want to support both MongoDB and MySQL in the same application
+ */
+public interface IFortune extends SimpleBean, Comparable<IFortune> {
+    Integer getId();
+    String getMessage();
+
+    @Override
+    default int compareTo(@NotNull IFortune o) {
+        return getMessage().compareTo(o.getMessage());
+    }
+}

+ 11 - 0
frameworks/Java/act/src/main/java/com/techempower/act/domain/IWorld.java

@@ -0,0 +1,11 @@
+package com.techempower.act.domain;
+
+import act.util.SimpleBean;
+
+/**
+ * We need this interface because we want to support both MongoDB and MySQL in the same application
+ */
+public interface IWorld extends SimpleBean {
+    Integer getId();
+    Integer getRandomNumber();
+}

+ 20 - 0
frameworks/Java/act/src/main/java/com/techempower/act/mongo/controller/FortuneController.java

@@ -0,0 +1,20 @@
+package com.techempower.act.mongo.controller;
+
+import act.controller.Controller;
+import act.db.morphia.MorphiaQuery;
+import com.techempower.act.controller.FortuneControllerBase;
+import com.techempower.act.mongo.domain.Fortune;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+@Singleton
+@Controller("mongo")
+public class FortuneController extends FortuneControllerBase<Fortune, MorphiaQuery<Fortune>, Fortune.Dao> {
+
+    @Inject
+    public FortuneController(Fortune.Dao fortuneDao) {
+        super(fortuneDao);
+    }
+
+}

+ 24 - 0
frameworks/Java/act/src/main/java/com/techempower/act/mongo/controller/WorldController.java

@@ -0,0 +1,24 @@
+package com.techempower.act.mongo.controller;
+
+import act.controller.Controller;
+import act.db.morphia.MorphiaQuery;
+import com.techempower.act.controller.WorldControllerBase;
+import com.techempower.act.mongo.domain.World;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+@Singleton
+@Controller("mongo")
+public final class WorldController extends WorldControllerBase<World, MorphiaQuery<World>, World.Dao> {
+
+	@Inject
+	public WorldController(World.Dao worldDao) {
+		super(worldDao);
+	}
+
+	@Override
+	protected World findAndModifyOne() {
+		return worldDao.ds().findAndModify(worldDao.q("_id", randomWorldNumber()), worldDao.updates().set("randomNumber", randomWorldNumber()));
+	}
+}

+ 35 - 0
frameworks/Java/act/src/main/java/com/techempower/act/mongo/domain/Fortune.java

@@ -0,0 +1,35 @@
+package com.techempower.act.mongo.domain;
+
+import act.db.DB;
+import act.db.morphia.MorphiaDaoBase;
+import act.util.SimpleBean;
+import com.techempower.act.domain.IFortune;
+import org.mongodb.morphia.annotations.Entity;
+import org.mongodb.morphia.annotations.Id;
+
+@DB("mongo")
+@Entity(noClassnameStored = true)
+public final class Fortune implements IFortune, SimpleBean {
+
+    @Id
+    private Integer id;
+
+    private String message;
+
+    public Fortune(Integer id, String message) {
+        this.id = id;
+        this.message = message;
+    }
+
+    public Integer getId() {
+        return id;
+    }
+
+    public String getMessage() {
+        return this.message;
+    }
+
+    public static class Dao extends MorphiaDaoBase<Integer, Fortune> {}
+
+
+}

+ 33 - 0
frameworks/Java/act/src/main/java/com/techempower/act/mongo/domain/World.java

@@ -0,0 +1,33 @@
+package com.techempower.act.mongo.domain;
+
+
+import act.db.DB;
+import act.db.morphia.MorphiaDaoBase;
+import com.techempower.act.domain.IWorld;
+import org.mongodb.morphia.annotations.Entity;
+import org.mongodb.morphia.annotations.Id;
+
+@DB("mongo")
+@Entity(noClassnameStored = true)
+public final class World implements IWorld {
+
+    @Id
+    private Integer id;
+
+    private Integer randomNumber;
+
+    public World(Integer id, Integer randomNumber) {
+        this.id = id;
+        this.randomNumber = randomNumber;
+    }
+
+    public Integer getId() {
+        return id;
+    }
+
+    public Integer getRandomNumber() {
+        return randomNumber;
+    }
+
+    public static class Dao extends MorphiaDaoBase<Integer, World> {}
+}

+ 16 - 0
frameworks/Java/act/src/main/java/com/techempower/act/mysql/controller/FortuneController.java

@@ -0,0 +1,16 @@
+package com.techempower.act.mysql.controller;
+
+import act.controller.Controller;
+import com.techempower.act.mysql.domain.Fortune;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+@Controller("mysql")
+@Singleton
+public class FortuneController extends com.techempower.act.controller.FortuneControllerBase<Fortune,act.db.ebean.EbeanQuery<Fortune>,Fortune.Dao> {
+    @Inject
+    public FortuneController(Fortune.Dao worldDao) {
+        super(worldDao);
+    }
+}

+ 17 - 0
frameworks/Java/act/src/main/java/com/techempower/act/mysql/controller/WorldController.java

@@ -0,0 +1,17 @@
+package com.techempower.act.mysql.controller;
+
+import act.controller.Controller;
+import com.techempower.act.mysql.domain.World;
+import com.techempower.act.sql.controller.SqlWorldControllerBase;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+@Controller("mysql")
+@Singleton
+public class WorldController extends SqlWorldControllerBase<World, World.Dao> {
+    @Inject
+    public WorldController(World.Dao worldDao) {
+        super(worldDao);
+    }
+}

+ 18 - 0
frameworks/Java/act/src/main/java/com/techempower/act/mysql/domain/Fortune.java

@@ -0,0 +1,18 @@
+package com.techempower.act.mysql.domain;
+
+
+import act.db.DB;
+import act.db.ebean.EbeanDao;
+
+import javax.persistence.Entity;
+
+@DB("mysql")
+@Entity
+public class Fortune extends com.techempower.act.sql.domain.Fortune {
+
+    public Fortune(Integer id, String message) {
+        super(id, message);
+    }
+
+    public static class Dao extends EbeanDao<Integer, Fortune> {}
+}

+ 17 - 0
frameworks/Java/act/src/main/java/com/techempower/act/mysql/domain/World.java

@@ -0,0 +1,17 @@
+package com.techempower.act.mysql.domain;
+
+
+import act.db.DB;
+import act.db.ebean.EbeanDao;
+
+import javax.persistence.Entity;
+
+@DB("mysql")
+@Entity
+public class World extends com.techempower.act.sql.domain.World {
+    public World(Integer id, Integer randomNumber) {
+        super(id, randomNumber);
+    }
+
+    public static class Dao extends EbeanDao<Integer, World> {}
+}

+ 16 - 0
frameworks/Java/act/src/main/java/com/techempower/act/pgsql/controller/FortuneController.java

@@ -0,0 +1,16 @@
+package com.techempower.act.pgsql.controller;
+
+import act.controller.Controller;
+import com.techempower.act.pgsql.domain.Fortune;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+@Controller("pgsql")
+@Singleton
+public class FortuneController extends com.techempower.act.controller.FortuneControllerBase<Fortune,act.db.ebean.EbeanQuery<Fortune>,Fortune.Dao> {
+    @Inject
+    public FortuneController(Fortune.Dao worldDao) {
+        super(worldDao);
+    }
+}

+ 17 - 0
frameworks/Java/act/src/main/java/com/techempower/act/pgsql/controller/WorldController.java

@@ -0,0 +1,17 @@
+package com.techempower.act.pgsql.controller;
+
+import act.controller.Controller;
+import com.techempower.act.pgsql.domain.World;
+import com.techempower.act.sql.controller.SqlWorldControllerBase;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+@Controller("pgsql")
+@Singleton
+public class WorldController extends SqlWorldControllerBase<World, World.Dao> {
+    @Inject
+    public WorldController(World.Dao worldDao) {
+        super(worldDao);
+    }
+}

+ 18 - 0
frameworks/Java/act/src/main/java/com/techempower/act/pgsql/domain/Fortune.java

@@ -0,0 +1,18 @@
+package com.techempower.act.pgsql.domain;
+
+
+import act.db.DB;
+import act.db.ebean.EbeanDao;
+
+import javax.persistence.Entity;
+
+@DB("pgsql")
+@Entity
+public class Fortune extends com.techempower.act.sql.domain.Fortune {
+
+    public Fortune(Integer id, String message) {
+        super(id, message);
+    }
+
+    public static class Dao extends EbeanDao<Integer, Fortune> {}
+}

+ 17 - 0
frameworks/Java/act/src/main/java/com/techempower/act/pgsql/domain/World.java

@@ -0,0 +1,17 @@
+package com.techempower.act.pgsql.domain;
+
+
+import act.db.DB;
+import act.db.ebean.EbeanDao;
+
+import javax.persistence.Entity;
+
+@DB("pgsql")
+@Entity
+public class World extends com.techempower.act.sql.domain.World {
+    public World(Integer id, Integer randomNumber) {
+        super(id, randomNumber);
+    }
+
+    public static class Dao extends EbeanDao<Integer, World> {}
+}

+ 25 - 0
frameworks/Java/act/src/main/java/com/techempower/act/sql/controller/SqlWorldControllerBase.java

@@ -0,0 +1,25 @@
+package com.techempower.act.sql.controller;
+
+import act.db.ebean.EbeanDao;
+import act.db.ebean.EbeanQuery;
+import com.techempower.act.controller.WorldControllerBase;
+import com.techempower.act.sql.domain.World;
+
+public abstract class SqlWorldControllerBase<
+		MODEL_TYPE extends World,
+		DAO_TYPE extends EbeanDao<Integer, MODEL_TYPE>>
+		extends WorldControllerBase<MODEL_TYPE, EbeanQuery<MODEL_TYPE>, DAO_TYPE> {
+
+	public SqlWorldControllerBase(DAO_TYPE worldDao) {
+		super(worldDao);
+	}
+
+	@Override
+	protected MODEL_TYPE findAndModifyOne() {
+		MODEL_TYPE model = findOne();
+		model.setRandomNumber(randomWorldNumber());
+		worldDao.ebean().update(model);
+		return model;
+	}
+
+}

+ 32 - 0
frameworks/Java/act/src/main/java/com/techempower/act/sql/domain/Fortune.java

@@ -0,0 +1,32 @@
+package com.techempower.act.sql.domain;
+
+import act.data.annotation.Data;
+import act.util.SimpleBean;
+import com.techempower.act.domain.IFortune;
+
+import javax.persistence.Id;
+import javax.persistence.MappedSuperclass;
+
+@Data
+@MappedSuperclass
+public class Fortune implements IFortune, SimpleBean {
+
+    @Id
+    private Integer id;
+
+    private String message;
+
+    public Fortune(Integer id, String message) {
+        this.id = id;
+        this.message = message;
+    }
+
+    public Integer getId() {
+        return id;
+    }
+
+    public String getMessage() {
+        return this.message;
+    }
+
+}

+ 40 - 0
frameworks/Java/act/src/main/java/com/techempower/act/sql/domain/World.java

@@ -0,0 +1,40 @@
+package com.techempower.act.sql.domain;
+
+
+import act.data.annotation.Data;
+import com.techempower.act.domain.IWorld;
+
+import javax.persistence.Column;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.MappedSuperclass;
+
+@Data
+@MappedSuperclass
+public class World implements IWorld {
+
+    @Id
+    @GeneratedValue
+    private Integer id;
+
+    @Column(name = "randomNumber")
+    private Integer randomNumber;
+
+    public World(Integer id, Integer randomNumber) {
+        this.id = id;
+        this.randomNumber = randomNumber;
+    }
+
+    public Integer getId() {
+        return id;
+    }
+
+    public Integer getRandomNumber() {
+        return randomNumber;
+    }
+
+    public void setRandomNumber(Integer randomNumber) {
+        this.randomNumber = randomNumber;
+    }
+
+}

+ 11 - 0
frameworks/Java/act/src/main/resources/conf/common/app.properties

@@ -0,0 +1,11 @@
+# follow Java world convention
+http.port=8080
+
+# disable CLI service
+cli=false
+
+# disable internal metric service
+metric=false
+
+# World max row is 10,000
+app.world.max_row=10000

+ 24 - 0
frameworks/Java/act/src/main/resources/conf/common/db.properties

@@ -0,0 +1,24 @@
+db.instances=mongo,mysql,pgsql
+
+mongo.host=localhost
+
+db.mongo.impl=act.db.morphia.MorphiaPlugin
+db.mongo.uri=mongodb://${mongo.host}/hello_world
+
+
+mysql.host=localhost
+
+db.mysql.impl=act.db.ebean.EbeanPlugin
+db.mysql.url=jdbc:mysql://${mysql.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.mysql.username=benchmarkdbuser
+db.mysql.password=benchmarkdbpass
+
+pgsql.host=localhost
+
+db.pgsql.impl=act.db.ebean.EbeanPlugin
+db.pgsql.url=jdbc:postgresql://${pgsql.host}:5432/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.pgsql.username=benchmarkdbuser
+db.pgsql.password=benchmarkdbpass
+db.pgsql.namingconvention=com.avaje.ebean.config.MatchingNamingConvention
+
+

+ 26 - 0
frameworks/Java/act/src/main/resources/logback.xml

@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+
+    <statusListener class="ch.qos.logback.core.status.NopStatusListener" />
+
+    <!-- Send debug messages to System.out -->
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <!-- By default, encoders are assigned the type ch.qos.logback.classic.encoder.PatternLayoutEncoder -->
+        <encoder>
+            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{5} - %msg%n</pattern>
+        </encoder>
+    </appender>
+
+    <logger name="act" level="INFO" additivity="false">
+        <appender-ref ref="STDOUT" />
+    </logger>
+
+    <logger name="metric" level="OFF">
+        <appender-ref ref="METRIC_FILE" />
+    </logger>
+
+    <!-- By default, the level of the root level is set to DEBUG -->
+    <root level="OFF">
+        <appender-ref ref="STDOUT" />
+    </root>
+</configuration>

+ 1 - 0
frameworks/Java/act/src/main/resources/routes.conf

@@ -0,0 +1 @@
+GET /plaintext echo: Hello, World!

+ 21 - 0
frameworks/Java/act/src/main/resources/rythm/fortunes.html

@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+@args List<com.techempower.act.domain.IFortune> fortunes;
+<html>
+<head>
+    <title>Fortunes</title>
+</head>
+<body>
+<table>
+    <tr>
+        <th>id</th>
+        <th>message</th>
+    </tr>
+    @for (fortunes) {
+    <tr>
+        <td>@_.getId()</td>
+        <td>@_.getMessage()</td>
+    </tr>
+    }
+</table>
+</body>
+</html>