Sfoglia il codice sorgente

add ActFramework benchmark set

Gelin Luo 8 anni fa
parent
commit
6db40e537e
38 ha cambiato i file con 1460 aggiunte e 0 eliminazioni
  1. 18 0
      frameworks/Java/act/.gitignore
  2. 420 0
      frameworks/Java/act/README.md
  3. 91 0
      frameworks/Java/act/benchmark_config.json
  4. 15 0
      frameworks/Java/act/pipeline.lua
  5. 140 0
      frameworks/Java/act/pom.xml
  6. 6 0
      frameworks/Java/act/run.sh
  7. 5 0
      frameworks/Java/act/setup-mongo.sh
  8. 5 0
      frameworks/Java/act/setup-mysql.sh
  9. 5 0
      frameworks/Java/act/setup-postgresql.sh
  10. 8 0
      frameworks/Java/act/setup.sh
  11. 28 0
      frameworks/Java/act/source_code
  12. 66 0
      frameworks/Java/act/src/assembly/pkg.xml
  13. 13 0
      frameworks/Java/act/src/main/java/com/techempower/act/AppEntry.java
  14. 32 0
      frameworks/Java/act/src/main/java/com/techempower/act/controller/FortuneControllerBase.java
  15. 40 0
      frameworks/Java/act/src/main/java/com/techempower/act/controller/HelloController.java
  16. 78 0
      frameworks/Java/act/src/main/java/com/techempower/act/controller/WorldControllerBase.java
  17. 17 0
      frameworks/Java/act/src/main/java/com/techempower/act/domain/IFortune.java
  18. 11 0
      frameworks/Java/act/src/main/java/com/techempower/act/domain/IWorld.java
  19. 20 0
      frameworks/Java/act/src/main/java/com/techempower/act/mongo/controller/FortuneController.java
  20. 24 0
      frameworks/Java/act/src/main/java/com/techempower/act/mongo/controller/WorldController.java
  21. 35 0
      frameworks/Java/act/src/main/java/com/techempower/act/mongo/domain/Fortune.java
  22. 33 0
      frameworks/Java/act/src/main/java/com/techempower/act/mongo/domain/World.java
  23. 16 0
      frameworks/Java/act/src/main/java/com/techempower/act/mysql/controller/FortuneController.java
  24. 17 0
      frameworks/Java/act/src/main/java/com/techempower/act/mysql/controller/WorldController.java
  25. 18 0
      frameworks/Java/act/src/main/java/com/techempower/act/mysql/domain/Fortune.java
  26. 17 0
      frameworks/Java/act/src/main/java/com/techempower/act/mysql/domain/World.java
  27. 16 0
      frameworks/Java/act/src/main/java/com/techempower/act/pgsql/controller/FortuneController.java
  28. 17 0
      frameworks/Java/act/src/main/java/com/techempower/act/pgsql/controller/WorldController.java
  29. 18 0
      frameworks/Java/act/src/main/java/com/techempower/act/pgsql/domain/Fortune.java
  30. 17 0
      frameworks/Java/act/src/main/java/com/techempower/act/pgsql/domain/World.java
  31. 24 0
      frameworks/Java/act/src/main/java/com/techempower/act/sql/controller/SqlWorldControllerBase.java
  32. 32 0
      frameworks/Java/act/src/main/java/com/techempower/act/sql/domain/Fortune.java
  33. 40 0
      frameworks/Java/act/src/main/java/com/techempower/act/sql/domain/World.java
  34. 3 0
      frameworks/Java/act/src/main/resources/conf/common/app.properties
  35. 24 0
      frameworks/Java/act/src/main/resources/conf/common/db.properties
  36. 3 0
      frameworks/Java/act/src/main/resources/conf/prod/app.properties
  37. 67 0
      frameworks/Java/act/src/main/resources/logback.xml
  38. 21 0
      frameworks/Java/act/src/main/resources/rythm/fortunes.html

+ 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
+

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

@@ -0,0 +1,420 @@
+# 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 or an embedded H2 database.
+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)
+
+##### 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
+
+##### 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.3.1-SNAPSHOT](http://actframework.org/)
+* [act-ebean plugin 0.3.1-SNAPSHOT](https://github.com/actframework/act-ebean)
+* [act-morphia plugin 0.4.1-SNAPSHOT](https://github.com/actframework/act-morphia)
+* [Undertow 1.4.8.Final](http://undertow.io/)
+
+
+## Local Test Result
+
+|            Test            | Throughput |  Latency  | Timeout |
+| -------------------------- | ---------- | --------- | ------- |
+| json                       |  340625.81 |    7.42ms |         |
+| single query - mongo       |   42852.18 |   25.83ms |         |
+| single query - mysql       |   23783.32 |   46.66ms |         |
+| single query - pgsql       |   33442.32 |   39.91ms |         |
+| 20 queries - mongo         |    2444.14 |  195.34ms |         |
+| 20 queries - mysql         |    1224.91 |       n/a |     768 |
+| 20 queries - pgsql         |    1792.12 |  453.02ms |     873 |
+| 20 updates - mongo         |    2031.09 |  167.19ms |         |
+| 20 updates - mysql         |     408.35 |       n/a |     256 |
+| 20 updates - pgsql         |     815.00 |       n/a |     512 |
+| fortunes - mongo           |   22062.14 |   87.88ms |         |
+| fortunes - mysql           |   20337.16 |   30.38ms |         |
+| fortunes - pgsql           |   22272.51 |   51.23ms |         |
+| plaintext                  |  346660.26 |    7.79ms |         |
+
+
+### 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     7.42ms    5.02ms 219.77ms   71.96%
+    Req/Sec    85.76k     9.76k  119.11k    68.25%
+  Latency Distribution
+     50%    6.71ms
+     75%   10.32ms
+     90%   13.38ms
+     99%   22.45ms
+  3412544 requests in 10.02s, 559.77MB read
+Requests/sec: 340625.81
+Transfer/sec:     55.87MB
+```
+
+#### 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     7.97ms    9.13ms 224.80ms   94.67%
+    Req/Sec    87.31k    11.06k  120.00k    74.50%
+  Latency Distribution
+     50%    6.64ms
+     75%   10.46ms
+     90%   14.16ms
+     99%   27.18ms
+  3475120 requests in 10.02s, 553.46MB read
+Requests/sec: 346660.26
+Transfer/sec:     55.21MB
+```
+
+#### 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    25.83ms   32.47ms 134.19ms    0.00%
+    Req/Sec    10.81k   823.82    15.03k    83.00%
+  Latency Distribution
+     50%    0.00us
+     75%    0.00us
+     90%    0.00us
+     99%    0.00us
+  430768 requests in 10.05s, 72.21MB read
+Requests/sec:  42852.18
+Transfer/sec:      7.18MB
+```
+
+#### 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    46.66ms   58.28ms 221.56ms    0.00%
+    Req/Sec     6.01k     1.45k   10.18k    76.26%
+  Latency Distribution
+     50%    0.00us
+     75%    0.00us
+     90%    0.00us
+     99%    0.00us
+  238656 requests in 10.03s, 40.01MB read
+Requests/sec:  23783.32
+Transfer/sec:      3.99MB
+```
+
+#### 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    39.91ms   42.89ms 247.65ms    1.56%
+    Req/Sec     8.44k   771.49    10.56k    82.71%
+  Latency Distribution
+     50%    0.00us
+     75%    0.00us
+     90%    0.00us
+     99%    0.00us
+  335936 requests in 10.05s, 56.32MB read
+Requests/sec:  33442.32
+Transfer/sec:      5.61MB
+```
+
+#### 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   195.34ms  466.91ms   1.62s     0.00%
+    Req/Sec     2.71k     3.28k    9.92k    78.72%
+  Latency Distribution
+     50%    0.00us
+     75%    0.00us
+     90%    0.00us
+     99%    0.00us
+  24576 requests in 10.06s, 18.34MB read
+Requests/sec:   2444.14
+Transfer/sec:      1.82MB
+```
+
+#### 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     2.51k     2.64k    8.16k    77.27%
+  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:   1224.91
+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   453.02ms  611.50ms   2.00s     0.00%
+    Req/Sec     1.01k     0.85k    4.32k    74.71%
+  Latency Distribution
+     50%    0.00us
+     75%    0.00us
+     90%    0.00us
+     99%    0.00us
+  18000 requests in 10.04s, 13.44MB read
+  Socket errors: connect 0, read 0, write 0, timeout 873
+Requests/sec:   1792.12
+Transfer/sec:      1.34MB
+```
+
+#### 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   167.19ms  495.91ms   1.88s     0.00%
+    Req/Sec     2.89k     3.53k    9.44k    75.00%
+  Latency Distribution
+     50%    0.00us
+     75%    0.00us
+     90%    0.00us
+     99%    0.00us
+  20480 requests in 10.08s, 15.28MB read
+Requests/sec:   2031.09
+Transfer/sec:      1.52MB
+```
+
+#### 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.47k     1.67k    5.33k    79.17%
+  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.35
+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     2.16k     2.02k    6.88k    57.58%
+  Latency Distribution
+     50%    0.00us
+     75%    0.00us
+     90%    0.00us
+     99%    0.00us
+  8192 requests in 10.05s, 6.11MB read
+  Socket errors: connect 0, read 0, write 0, timeout 512
+Requests/sec:    815.00
+Transfer/sec:    622.85KB
+```
+
+#### 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    87.88ms   45.47ms 397.54ms   39.55%
+    Req/Sec     5.58k     1.10k    9.57k    73.75%
+  Latency Distribution
+     50%  152.88ms
+     75%    0.00us
+     90%    0.00us
+     99%    0.00us
+  222176 requests in 10.07s, 306.17MB read
+Requests/sec:  22062.14
+Transfer/sec:     30.40MB
+```
+
+#### 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    30.38ms   64.32ms 274.78ms    0.00%
+    Req/Sec     5.14k     1.98k    9.74k    73.99%
+  Latency Distribution
+     50%    0.00us
+     75%    0.00us
+     90%    0.00us
+     99%    0.00us
+  204644 requests in 10.06s, 282.01MB read
+Requests/sec:  20337.16
+Transfer/sec:     28.03MB
+```
+
+#### Fortunes - Postgresql
+
+```
+luog@luog-Satellite-P50-A:~/p/greenlaw110/webframework-benchmark$ 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    51.23ms   63.86ms 324.07ms    0.00%
+    Req/Sec     5.62k     1.00k   10.14k    79.85%
+  Latency Distribution
+     50%    0.00us
+     75%    0.00us
+     90%    0.00us
+     99%    0.00us
+  223780 requests in 10.05s, 308.38MB read
+Requests/sec:  22272.51
+Transfer/sec:     30.69MB
+```

+ 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": ""
+    },
+    "pgsql": {
+      "setup_file": "setup-postgresql",
+      "db_url": "/pgsql/db",
+      "query_url": "/pgsql/queries?queries=",
+      "fortune_url": "/pgsql/fortunes",
+      "update_url": "/pgsql/update?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": ""
+    },
+    "mysql": {
+      "setup_file": "setup-mysql",
+      "db_url": "/mysql/db",
+      "query_url": "/mysql/queries?queries=",
+      "fortune_url": "/mysql/fortunes",
+      "update_url": "/mysql/update?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": ""
+    },
+    "mongodb": {
+      "setup_file": "setup-mongodb",
+      "db_url": "/mongo/db",
+      "query_url": "/mongo/queries?queries=",
+      "fortune_url": "/mongo/fortunes",
+      "update_url": "/mongo/update?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": ""
+    }
+  }]
+}

+ 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

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

@@ -0,0 +1,140 @@
+<?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.3.1-SNAPSHOT</act.version>
+        <act-morphia.version>0.4.1-SNAPSHOT</act-morphia.version>
+        <act-ebean.version>0.3.1-SNAPSHOT</act-ebean.version>
+        <h2.version>1.4.193</h2.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>com.h2database</groupId>
+            <artifactId>h2</artifactId>
+            <version>${h2.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

+ 5 - 0
frameworks/Java/act/setup-mongo.sh

@@ -0,0 +1,5 @@
+#!/bin/bash
+
+fw_depends mongodb
+
+source ./setup.sh

+ 5 - 0
frameworks/Java/act/setup-mysql.sh

@@ -0,0 +1,5 @@
+#!/bin/bash
+
+fw_depends mysql
+
+source ./setup.sh

+ 5 - 0
frameworks/Java/act/setup-postgresql.sh

@@ -0,0 +1,5 @@
+#!/bin/bash
+
+fw_depends postgresql
+
+source ./setup.sh

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

@@ -0,0 +1,8 @@
+#!/bin/bash
+
+fw_depends mysql postgresql mongodb java maven
+
+mvn clean package
+cd target/dist
+unzip *.zip
+./start -Dmongo.host=${DBHOST} -Dmysql.host=${DBHOST} -Dpgsql.host=${DBHOST}

+ 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>

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

@@ -0,0 +1,13 @@
+package com.techempower.act;
+
+
+import act.Version;
+import act.boot.app.RunApp;
+
+public class AppEntry {
+
+	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);
+
+        render("fortunes", fortunes);
+    }
+
+}

+ 40 - 0
frameworks/Java/act/src/main/java/com/techempower/act/controller/HelloController.java

@@ -0,0 +1,40 @@
+package com.techempower.act.controller;
+
+import act.controller.Controller;
+import org.osgl.mvc.annotation.GetAction;
+import org.osgl.mvc.annotation.SessionFree;
+
+import javax.inject.Singleton;
+
+@Singleton
+final class HelloController extends Controller.Util {
+
+    private static final String HELLO_WORLD = "Hello, World!";
+
+	@GetAction("/json")
+    @SessionFree
+    public void json() throws Exception {
+        json(new Message("Hello, World!"));
+    }
+
+    @GetAction("/plaintext")
+    @SessionFree
+    public void plaintext() {
+        text(HELLO_WORLD);
+    }
+
+    public static final class Message {
+
+        private final String message;
+
+        private Message(String message) {
+            this.message = message;
+        }
+
+        public String getMessage() {
+            return message;
+        }
+
+    }
+
+}

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

@@ -0,0 +1,78 @@
+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(Integer queries) {
+		int q = regulateQueries(queries);
+
+		List<IWorld> retVal = new ArrayList<>();
+		for (int i = 0; i < q; ++i) {
+			retVal.add(findOne());
+		}
+		json(retVal);
+	}
+
+	@GetAction("updates")
+	public final void updateQueries(Integer queries) {
+		int q = regulateQueries(queries);
+		List<IWorld> 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();
+
+	protected final int regulateQueries(Integer param) {
+		if (null == param) {
+			return 1;
+		}
+		if (param < 1) {
+			return 1;
+		}
+		return param > 500 ? 500 : param;
+	}
+
+	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> {}
+}

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

@@ -0,0 +1,24 @@
+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.save(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;
+    }
+
+}

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

@@ -0,0 +1,3 @@
+#http.port=8080
+#cli.port=8081
+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
+
+

+ 3 - 0
frameworks/Java/act/src/main/resources/conf/prod/app.properties

@@ -0,0 +1,3 @@
+http.port=8080
+cli.port=8081
+

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

@@ -0,0 +1,67 @@
+<?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>
+
+    <!-- Send debug messages to a file at "c:/jcg.log" -->
+    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>act.log</file>
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <Pattern>%d{yyyy-MM-dd_HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
+        </encoder>
+
+        <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
+            <FileNamePattern>/jcg.%i.log.zip</FileNamePattern>
+            <MinIndex>1</MinIndex>
+            <MaxIndex>10</MaxIndex>
+        </rollingPolicy>
+
+        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
+            <MaxFileSize>2MB</MaxFileSize>
+        </triggeringPolicy>
+    </appender>
+
+    <appender name="METRIC_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>act.metric.log</file>
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <Pattern>%d{yyyy-MM-dd_HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
+        </encoder>
+
+        <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
+            <FileNamePattern>/jcg.%i.log.zip</FileNamePattern>
+            <MinIndex>1</MinIndex>
+            <MaxIndex>10</MaxIndex>
+        </rollingPolicy>
+
+        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
+            <MaxFileSize>2MB</MaxFileSize>
+        </triggeringPolicy>
+    </appender>
+
+    <logger name="act" level="INFO" additivity="false">
+        <appender-ref ref="FILE" />
+        <appender-ref ref="STDOUT" />
+    </logger>
+
+    <logger name="metric.act" level="OFF">
+        <appender-ref ref="METRIC_FILE" />
+    </logger>
+
+    <logger name="demo.helloworld.PersonController" level="DEBUG" additivity="false">
+        <appender-ref ref="STDOUT" />
+    </logger>
+
+
+    <!-- By default, the level of the root level is set to DEBUG -->
+    <root level="INFO">
+        <appender-ref ref="STDOUT" />
+    </root>
+</configuration>

+ 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>