瀏覽代碼

Merge branch 'master' of https://github.com/TechEmpower/FrameworkBenchmarks

Adam Chlipala 10 年之前
父節點
當前提交
21dce8a056
共有 100 個文件被更改,包括 2315 次插入718 次删除
  1. 15 10
      .travis.yml
  2. 24 0
      frameworks/Clojure/aleph/README.md
  3. 24 0
      frameworks/Clojure/aleph/benchmark_config.json
  4. 11 0
      frameworks/Clojure/aleph/hello/.gitignore
  5. 9 0
      frameworks/Clojure/aleph/hello/project.clj
  6. 44 0
      frameworks/Clojure/aleph/hello/src/hello/handler.clj
  7. 0 0
      frameworks/Clojure/aleph/hello/src/log4j.xml
  8. 3 0
      frameworks/Clojure/aleph/install.sh
  9. 10 0
      frameworks/Clojure/aleph/setup.sh
  10. 2 0
      frameworks/Clojure/aleph/source_code
  11. 10 29
      frameworks/Clojure/luminus/benchmark_config.json
  12. 3 4
      frameworks/Clojure/luminus/hello/.gitignore
  13. 1 0
      frameworks/Clojure/luminus/hello/Procfile
  14. 1 1
      frameworks/Clojure/luminus/hello/README.md
  15. 34 0
      frameworks/Clojure/luminus/hello/env/dev/clj/hello/repl.clj
  16. 48 39
      frameworks/Clojure/luminus/hello/project.clj
  17. 5 54
      frameworks/Clojure/luminus/hello/resources/public/css/screen.css
  18. 20 0
      frameworks/Clojure/luminus/hello/resources/sql/queries.sql
  19. 0 0
      frameworks/Clojure/luminus/hello/resources/templates/base.html
  20. 3 3
      frameworks/Clojure/luminus/hello/resources/templates/home.html
  21. 30 0
      frameworks/Clojure/luminus/hello/src/hello/core.clj
  22. 69 0
      frameworks/Clojure/luminus/hello/src/hello/db/core.clj
  23. 34 34
      frameworks/Clojure/luminus/hello/src/hello/handler.clj
  24. 37 0
      frameworks/Clojure/luminus/hello/src/hello/layout.clj
  25. 37 0
      frameworks/Clojure/luminus/hello/src/hello/middleware.clj
  26. 0 94
      frameworks/Clojure/luminus/hello/src/hello/models/db.clj
  27. 0 39
      frameworks/Clojure/luminus/hello/src/hello/models/schema.clj
  28. 24 50
      frameworks/Clojure/luminus/hello/src/hello/routes/home.clj
  29. 21 0
      frameworks/Clojure/luminus/hello/src/hello/session.clj
  30. 0 10
      frameworks/Clojure/luminus/hello/src/hello/views/layout.clj
  31. 2 4
      frameworks/Clojure/luminus/hello/test/hello/test/handler.clj
  32. 6 12
      frameworks/Clojure/luminus/setup.sh
  33. 23 14
      frameworks/Clojure/luminus/source_code
  34. 2 2
      frameworks/Java/netty/pom.xml
  35. 1 1
      frameworks/Java/play2-java/install.sh
  36. 2 2
      frameworks/Java/play2-java/play2-java-ebean-bonecp/build.sbt
  37. 1 1
      frameworks/Java/play2-java/play2-java-ebean-bonecp/project/plugins.sbt
  38. 3 3
      frameworks/Java/play2-java/play2-java-ebean-hikaricp/build.sbt
  39. 46 18
      frameworks/Java/play2-java/play2-java-ebean-hikaricp/conf/application.conf
  40. 1 1
      frameworks/Java/play2-java/play2-java-ebean-hikaricp/project/plugins.sbt
  41. 3 3
      frameworks/Java/play2-java/play2-java-jpa-bonecp/build.sbt
  42. 1 1
      frameworks/Java/play2-java/play2-java-jpa-bonecp/project/plugins.sbt
  43. 4 4
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/build.sbt
  44. 47 19
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/conf/application.conf
  45. 1 1
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/project/plugins.sbt
  46. 1 1
      frameworks/Java/play2-java/play2-java/build.sbt
  47. 1 1
      frameworks/Java/play2-java/play2-java/project/plugins.sbt
  48. 1 1
      frameworks/Java/play2-java/setup_java.sh
  49. 1 1
      frameworks/Java/play2-java/setup_java_ebean_bonecp.sh
  50. 1 1
      frameworks/Java/play2-java/setup_java_ebean_hikaricp.sh
  51. 1 1
      frameworks/Java/play2-java/setup_java_jpa_bonecp.sh
  52. 1 1
      frameworks/Java/play2-java/setup_java_jpa_hikaricp.sh
  53. 78 2
      frameworks/Java/sabina/benchmark_config.json
  54. 3 0
      frameworks/Java/sabina/jetty-mongodb.sh
  55. 3 0
      frameworks/Java/sabina/jetty.sh
  56. 6 1
      frameworks/Java/sabina/pom.xml
  57. 1 1
      frameworks/Java/sabina/setup.sh
  58. 59 134
      frameworks/Java/sabina/src/main/java/sabina/benchmark/Application.java
  59. 0 5
      frameworks/Java/sabina/src/main/java/sabina/benchmark/Fortune.java
  60. 91 0
      frameworks/Java/sabina/src/main/java/sabina/benchmark/MongoDbRepository.java
  61. 139 0
      frameworks/Java/sabina/src/main/java/sabina/benchmark/MySqlRepository.java
  62. 22 0
      frameworks/Java/sabina/src/main/java/sabina/benchmark/Repository.java
  63. 5 2
      frameworks/Java/sabina/src/main/resources/server.properties
  64. 13 28
      frameworks/Java/sabina/src/test/java/sabina/benchmark/ApplicationTest.java
  65. 3 0
      frameworks/Java/sabina/undertow-mongodb.sh
  66. 3 0
      frameworks/Java/sabina/undertow.sh
  67. 1 1
      frameworks/Java/undertow/install.sh
  68. 10 10
      frameworks/Java/undertow/pom.xml
  69. 2 2
      frameworks/Java/undertow/setup.sh
  70. 2 0
      frameworks/Java/undertow/src/main/java/hello/HelloWebServer.java
  71. 43 6
      frameworks/Java/vertx/README.md
  72. 139 38
      frameworks/Java/vertx/WebServer.java
  73. 1 1
      frameworks/Java/vertx/app.js
  74. 2 0
      frameworks/Java/vertx/benchmark_config.json
  75. 1 1
      frameworks/Java/vertx/install.sh
  76. 51 21
      frameworks/Lua/openresty/app.lua
  77. 2 1
      frameworks/Lua/openresty/benchmark_config.json
  78. 3 1
      frameworks/Lua/openresty/install.sh
  79. 11 2
      frameworks/Lua/openresty/nginx.conf
  80. 1 1
      frameworks/PHP/codeigniter/install.sh
  81. 63 0
      frameworks/PHP/cygnite-php-framework/.gitignore
  82. 28 0
      frameworks/PHP/cygnite-php-framework/.htaccess
  83. 8 0
      frameworks/PHP/cygnite-php-framework/.travis.yml
  84. 20 0
      frameworks/PHP/cygnite-php-framework/LICENSE
  85. 54 0
      frameworks/PHP/cygnite-php-framework/README.md
  86. 1 0
      frameworks/PHP/cygnite-php-framework/apps/.htaccess
  87. 0 0
      frameworks/PHP/cygnite-php-framework/apps/components/authentication/.gitkeep
  88. 0 0
      frameworks/PHP/cygnite-php-framework/apps/components/form/.gitkeep
  89. 235 0
      frameworks/PHP/cygnite-php-framework/apps/configs/application.php
  90. 35 0
      frameworks/PHP/cygnite-php-framework/apps/configs/autoload.php
  91. 55 0
      frameworks/PHP/cygnite-php-framework/apps/configs/database.php
  92. 77 0
      frameworks/PHP/cygnite-php-framework/apps/configs/definitions/DefinitionManager.php
  93. 69 0
      frameworks/PHP/cygnite-php-framework/apps/configs/migration.php
  94. 27 0
      frameworks/PHP/cygnite-php-framework/apps/configs/services.php
  95. 105 0
      frameworks/PHP/cygnite-php-framework/apps/configs/session.php
  96. 94 0
      frameworks/PHP/cygnite-php-framework/apps/controllers/BenchController.php
  97. 80 0
      frameworks/PHP/cygnite-php-framework/apps/controllers/HomeController.php
  98. 0 0
      frameworks/PHP/cygnite-php-framework/apps/database/.gitkeep
  99. 0 0
      frameworks/PHP/cygnite-php-framework/apps/database/migrations/.gitkeep
  100. 0 0
      frameworks/PHP/cygnite-php-framework/apps/extensions/.gitkeep

+ 15 - 10
.travis.yml

@@ -1,5 +1,5 @@
 language: python
 language: python
-python: 
+python:
   - "2.7"
   - "2.7"
 
 
 env:
 env:
@@ -9,12 +9,12 @@ env:
     # we end up starting ~200+ different workers. Seems that ~100 is the limit
     # we end up starting ~200+ different workers. Seems that ~100 is the limit
     # before their website starts to lag heavily
     # before their website starts to lag heavily
     #
     #
-    # Here's the bash if you need to update this. Be sure to maintain the 
+    # Here's the bash if you need to update this. Be sure to maintain the
     # lines that are currently commented out (these cannot run in Travis)
     # lines that are currently commented out (these cannot run in Travis)
-    #   cd frameworks 
+    #   cd frameworks
     #   find . -type d -depth 2 | sed 's|./|    - "TESTDIR=|' | sed 's/$/"/g'
     #   find . -type d -depth 2 | sed 's|./|    - "TESTDIR=|' | sed 's/$/"/g'
     #
     #
-    #  
+    #
     - "TESTDIR=C/lwan"
     - "TESTDIR=C/lwan"
     - "TESTDIR=C/duda"
     - "TESTDIR=C/duda"
     - "TESTDIR=C/haywire"
     - "TESTDIR=C/haywire"
@@ -34,6 +34,7 @@ env:
     - "TESTDIR=Clojure/http-kit"
     - "TESTDIR=Clojure/http-kit"
     - "TESTDIR=Clojure/luminus"
     - "TESTDIR=Clojure/luminus"
     - "TESTDIR=Clojure/pedestal"
     - "TESTDIR=Clojure/pedestal"
+    - "TESTDIR=Clojure/aleph"
     - "TESTDIR=Dart/dart"
     - "TESTDIR=Dart/dart"
     - "TESTDIR=Dart/dart-redstone"
     - "TESTDIR=Dart/dart-redstone"
     - "TESTDIR=Dart/dart-start"
     - "TESTDIR=Dart/dart-start"
@@ -98,6 +99,7 @@ env:
     - "TESTDIR=PHP/cakephp"
     - "TESTDIR=PHP/cakephp"
     - "TESTDIR=PHP/hhvm"
     - "TESTDIR=PHP/hhvm"
     - "TESTDIR=PHP/php"
     - "TESTDIR=PHP/php"
+    - "TESTDIR=PHP/cygnite-php-framework"
     - "TESTDIR=PHP/codeigniter"
     - "TESTDIR=PHP/codeigniter"
     - "TESTDIR=PHP/php-fatfree"
     - "TESTDIR=PHP/php-fatfree"
     - "TESTDIR=PHP/fuel"
     - "TESTDIR=PHP/fuel"
@@ -126,6 +128,7 @@ env:
     - "TESTDIR=Python/django"
     - "TESTDIR=Python/django"
     - "TESTDIR=Python/falcon"
     - "TESTDIR=Python/falcon"
     - "TESTDIR=Python/flask"
     - "TESTDIR=Python/flask"
+    - "TESTDIR=Python/historical"
     - "TESTDIR=Python/klein"
     - "TESTDIR=Python/klein"
     - "TESTDIR=Python/pyramid"
     - "TESTDIR=Python/pyramid"
     - "TESTDIR=Python/tornado"
     - "TESTDIR=Python/tornado"
@@ -142,6 +145,8 @@ env:
     - "TESTDIR=Ruby/rails"
     - "TESTDIR=Ruby/rails"
     - "TESTDIR=Ruby/rails-stripped"
     - "TESTDIR=Ruby/rails-stripped"
     - "TESTDIR=Ruby/sinatra"
     - "TESTDIR=Ruby/sinatra"
+    - "TESTDIR=Scala/akka-http"
+    - "TESTDIR=Scala/colossus"
     - "TESTDIR=Scala/finagle"
     - "TESTDIR=Scala/finagle"
     - "TESTDIR=Scala/lift-stateless"
     - "TESTDIR=Scala/lift-stateless"
     - "TESTDIR=Scala/plain"
     - "TESTDIR=Scala/plain"
@@ -155,7 +160,7 @@ env:
     - "TESTDIR=Ur/urweb"
     - "TESTDIR=Ur/urweb"
 
 
 before_install:
 before_install:
-  # Need to install python modules before using 
+  # Need to install python modules before using
   # python
   # python
   - pip install -r requirements.txt
   - pip install -r requirements.txt
 
 
@@ -164,15 +169,15 @@ before_install:
   - ./toolset/run-ci.py cisetup "$TESTDIR"
   - ./toolset/run-ci.py cisetup "$TESTDIR"
 
 
 addons:
 addons:
-  postgresql: "9.3" 
+  postgresql: "9.3"
 
 
 install:
 install:
   # Install prerequisites
   # Install prerequisites
   - ./toolset/run-ci.py prereq "$TESTDIR"
   - ./toolset/run-ci.py prereq "$TESTDIR"
-  
-  # Install software for this framework  
+
+  # Install software for this framework
   - ./toolset/run-ci.py install "$TESTDIR"
   - ./toolset/run-ci.py install "$TESTDIR"
-   
-script: 
+
+script:
   # Pick one test in this directory and verify
   # Pick one test in this directory and verify
   - time ./toolset/run-ci.py verify "$TESTDIR"
   - time ./toolset/run-ci.py verify "$TESTDIR"

+ 24 - 0
frameworks/Clojure/aleph/README.md

@@ -0,0 +1,24 @@
+# Compojure Benchmarking Test
+
+This is the [Aleph](https;//github.com/ztellman/aleph) portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+
+### JSON Encoding Test
+
+* [JSON test source](hello/src/hello/handler.clj)
+
+## Infrastructure Software Versions
+The dependencies are documented in [project.clj](hello/project.clj),
+but the main ones are:
+
+* [Aleph 0.4.0](https://github.com/ztellman/aleph)
+* [Clojure 1.7.0-beta2](http://clojure.org/)
+* [Cheshire 5.4.0](https://github.com/dakrone/cheshire), which in turn uses [Jackson](http://jackson.codehaus.org/)
+
+## Test URLs
+### JSON Encoding Test
+
+http://localhost/json
+
+### Plaintext Test
+
+http://localhost/plaintext

+ 24 - 0
frameworks/Clojure/aleph/benchmark_config.json

@@ -0,0 +1,24 @@
+{
+  "framework": "aleph",
+  "tests": [{
+    "default": {
+      "setup_file": "setup",
+      "json_url": "/json",
+      "plaintext_url": "/plaintext",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Platform",
+      "database": "None",
+      "framework": "aleph",
+      "language": "Clojure",
+      "orm": "Raw",
+      "platform": "Netty",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "aleph",
+      "notes": "",
+      "versus": "netty"
+    }
+  }]
+}

+ 11 - 0
frameworks/Clojure/aleph/hello/.gitignore

@@ -0,0 +1,11 @@
+/target
+/lib
+/classes
+/checkouts
+pom.xml
+*.jar
+*.class
+.lein-deps-sum
+.lein-failures
+.lein-plugins
+.lein-env

+ 9 - 0
frameworks/Clojure/aleph/hello/project.clj

@@ -0,0 +1,9 @@
+(defproject hello "aleph"
+  :description "JSON/plaintext tests"
+  :dependencies [[org.clojure/clojure "1.7.0-beta2"]
+                 [clj-tuple "0.2.1"]
+                 [org.clojure/tools.cli "0.3.1"]
+                 [aleph "0.4.0"]
+                 [cheshire "5.4.0"]]
+  :main hello.handler
+  :aot :all)

+ 44 - 0
frameworks/Clojure/aleph/hello/src/hello/handler.clj

@@ -0,0 +1,44 @@
+(ns hello.handler
+  (:require
+    [byte-streams :as bs]
+    [clojure.tools.cli :as cli]
+    [aleph.http :as http]
+    [cheshire.core :as json]
+    [clj-tuple :as t])
+  (:gen-class))
+
+(def plaintext-response
+  (t/hash-map
+    :status 200
+    :headers (t/hash-map "content-type" "text/plain; charset=utf-8")
+    :body (bs/to-byte-array "Hello, World!")))
+
+(def json-response
+  (t/hash-map
+    :status 200
+    :headers (t/hash-map "content-type" "application/json")))
+
+(defn handler [{:keys [uri] :as req}]
+  (cond
+    (= "/plaintext" uri) plaintext-response
+    (= "/json" uri) (assoc json-response
+                      :body (json/encode (t/hash-map :message "Hello, World!")))
+    :else {:status 404}))
+
+;;;
+
+(defn -main [& args]
+
+  (let [[{:keys [help port]} _ banner]
+        (cli/cli args
+          ["-p" "--port" "Server port"
+           :default 8080
+           :parse-fn #(Integer/parseInt %)]
+          ["-h" "--[no-]help"])]
+
+    (when help
+      (println banner)
+      (System/exit 0))
+
+    (aleph.netty/leak-detector-level! :disabled)
+    (http/start-server handler {:port port, :executor :none})))

+ 0 - 0
frameworks/Clojure/luminus/hello/src/log4j.xml → frameworks/Clojure/aleph/hello/src/log4j.xml


+ 3 - 0
frameworks/Clojure/aleph/install.sh

@@ -0,0 +1,3 @@
+#!/bin/bash
+
+fw_depends java7 leiningen

+ 10 - 0
frameworks/Clojure/aleph/setup.sh

@@ -0,0 +1,10 @@
+#!/bin/bash
+
+source $IROOT/java7.installed
+
+source $IROOT/lein.installed
+
+cd hello
+lein clean
+lein uberjar
+java -server -Xmx2g -XX:+UseG1GC -XX:MaxGCPauseMillis=10 -jar target/*-standalone.jar &

+ 2 - 0
frameworks/Clojure/aleph/source_code

@@ -0,0 +1,2 @@
+./aleph/hello/src/hello/handler.clj
+./aleph/hello/project.clj

+ 10 - 29
frameworks/Clojure/luminus/benchmark_config.json

@@ -3,45 +3,26 @@
   "tests": [{
   "tests": [{
     "default": {
     "default": {
       "setup_file": "setup",
       "setup_file": "setup",
-      "json_url": "/luminus/json",
-      "db_url": "/luminus/db",
-      "query_url": "/luminus/db/",
-      "fortune_url": "/luminus/fortune",
-      "update_url": "/luminus/update/",
-      "plaintext_url": "/luminus/plaintext",
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/queries/",
+      "fortune_url": "/fortunes",
+      "update_url": "/updates/",
+      "plaintext_url": "/plaintext",
       "port": 8080,
       "port": 8080,
       "approach": "Realistic",
       "approach": "Realistic",
-      "classification": "Micro",
-      "database": "MySQL",
-      "framework": "luminus",
-      "language": "Clojure",
-      "orm": "Full",
-      "platform": "Servlet",
-      "webserver": "Resin",
-      "os": "Linux",
-      "database_os": "Linux",
-      "display_name": "luminus",
-      "notes": "",
-      "versus": "servlet"
-    },
-    "raw": {
-      "setup_file": "setup",
-      "db_url": "/luminus/dbraw",
-      "query_url": "/luminus/dbraw/",
-      "port": 8080,
-      "approach": "Realistic",
-      "classification": "Micro",
+      "classification": "Platform",
       "database": "MySQL",
       "database": "MySQL",
       "framework": "luminus",
       "framework": "luminus",
       "language": "Clojure",
       "language": "Clojure",
       "orm": "Raw",
       "orm": "Raw",
-      "platform": "Servlet",
-      "webserver": "Resin",
+      "platform": "http-kit",
+      "webserver": "None",
       "os": "Linux",
       "os": "Linux",
       "database_os": "Linux",
       "database_os": "Linux",
       "display_name": "luminus",
       "display_name": "luminus",
       "notes": "",
       "notes": "",
-      "versus": "servlet"
+      "versus": ""
     }
     }
   }]
   }]
 }
 }

+ 3 - 4
frameworks/Clojure/luminus/hello/.gitignore

@@ -5,7 +5,6 @@
 pom.xml
 pom.xml
 *.jar
 *.jar
 *.class
 *.class
-.lein-deps-sum
-.lein-failures
-.lein-plugins
-.lein-env
+/.lein-*
+/.env
+*.log

+ 1 - 0
frameworks/Clojure/luminus/hello/Procfile

@@ -0,0 +1 @@
+web: java $JVM_OPTS -cp target/hello.jar clojure.main -m hello.core

+ 1 - 1
frameworks/Clojure/luminus/hello/README.md

@@ -16,4 +16,4 @@ To start a web server for the application, run:
 
 
 ## License
 ## License
 
 
-Copyright © 2013 FIXME
+Copyright © 2015 FIXME

+ 34 - 0
frameworks/Clojure/luminus/hello/env/dev/clj/hello/repl.clj

@@ -0,0 +1,34 @@
+(ns hello.repl
+  (:use hello.handler
+    ring.server.standalone
+    [ring.middleware file-info file]))
+
+(defonce server (atom nil))
+
+(defn get-handler []
+  ;; #'app expands to (var app) so that when we reload our code,
+  ;; the server is forced to re-resolve the symbol in the var
+  ;; rather than having its own copy. When the root binding
+  ;; changes, the server picks it up without having to restart.
+  (-> #'app
+      ; Makes static assets in $PROJECT_DIR/resources/public/ available.
+      (wrap-file "resources")
+      ; Content-Type, Content-Length, and Last Modified headers for files in body
+      (wrap-file-info)))
+
+(defn start-server
+  "used for starting the server in development mode from REPL"
+  [& [port]]
+  (let [port (if port (Integer/parseInt port) 3000)]
+    (reset! server
+            (serve (get-handler)
+                   {:port port
+                    :init init
+                    :auto-reload? true
+                    :destroy destroy
+                    :join? false}))
+    (println (str "You can view the site at http://localhost:" port))))
+
+(defn stop-server []
+  (.stop @server)
+  (reset! server nil))

+ 48 - 39
frameworks/Clojure/luminus/hello/project.clj

@@ -1,40 +1,49 @@
-(defproject
-  hello
-  "luminus"
-  :dependencies
-  [[org.clojure/clojure "1.5.1"]
-   [lib-noir "0.8.2"]
-   [compojure "1.1.6"]
-   [ring-server "0.3.1"]
-   [selmer "0.5.7"]
-   [com.taoensso/timbre "2.7.1"]
-   [com.postspectacular/rotor "0.1.0"]
-   [com.taoensso/tower "2.0.2"]
-   [mysql/mysql-connector-java "5.1.28"]
-   [korma "0.3.0-RC6"]
-   [c3p0/c3p0 "0.9.1.2"]
-   [log4j
-    "1.2.17"
-    :exclusions
-    [javax.mail/mail
-     javax.jms/jms
-     com.sun.jdmk/jmxtools
-     com.sun.jmx/jmxri]]]
-  :ring
-  {:handler hello.handler/app,
-   :init hello.handler/init,
-   :destroy hello.handler/destroy}
+(defproject hello "luminus"
+
+  :description "Luminus framework benchmarks"
+  :url "https://github.com/TechEmpower/FrameworkBenchmarks/tree/master/frameworks/Clojure/luminus"
+
+  :dependencies [[org.clojure/clojure "1.6.0"]
+                 [ring-server "0.4.0"]
+                 [selmer "0.8.2"]
+                 [com.taoensso/timbre "3.4.0"]
+                 [com.taoensso/tower "3.0.2"]
+                 [markdown-clj "0.9.65"]
+                 [environ "1.0.0"]
+                 [im.chit/cronj "1.4.3"]
+                 [compojure "1.3.3"]
+                 [ring/ring-defaults "0.1.4"]
+                 [ring/ring-session-timeout "0.1.0"]
+                 [ring-middleware-format "0.5.0"]
+                 [noir-exception "0.2.3"]
+                 [bouncer "0.3.2"]
+                 [prone "0.8.1"]
+                 [org.clojure/tools.nrepl "0.2.8"]
+                 [yesql "0.5.0-rc2"]
+                 [mysql/mysql-connector-java "5.1.6"]
+                 [c3p0/c3p0 "0.9.1.2"]
+                 [http-kit "2.1.19"]
+                 [org.clojure/tools.cli "0.2.1"]]
+
+  :min-lein-version "2.0.0"
+  :uberjar-name "hello.jar"
+  :jvm-opts ["-server"]
+
+  :main hello.core
+
+  :plugins [[lein-ring "0.9.1"]
+            [lein-environ "1.0.0"]]
+
   :profiles
   :profiles
-  {:uberjar {:aot :all}
-   :production
-   {:ring
-    {:open-browser? false, :stacktraces? false, :auto-reload? false}},
-   :dev
-   {:dependencies [[ring-mock "0.1.5"] [ring/ring-devel "1.2.2"]]}}
-  :url
-  "http://example.com/FIXME"
-  :plugins
-  [[lein-ring "0.8.10"]]
-  :description
-  "FIXME: write description"
-  :min-lein-version "2.0.0")
+  {:uberjar {:omit-source true
+             :env {:production true}
+             :aot :all}
+   :dev {:dependencies [[ring-mock "0.1.5"]
+                        [ring/ring-devel "1.3.2"]
+                        [pjstadig/humane-test-output "0.7.0"]]
+         :source-paths ["env/dev/clj"]
+
+         :repl-options {:init-ns hello.repl}
+         :injections [(require 'pjstadig.humane-test-output)
+                      (pjstadig.humane-test-output/activate!)]
+         :env {:dev true}}})

+ 5 - 54
frameworks/Clojure/luminus/hello/resources/public/css/screen.css

@@ -1,55 +1,6 @@
-body {	
-    background-color: #fff;
-    color: #333;
-    font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
+html,
+body {
+	font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
+    height: 100%;
+    padding-top: 40px;
 }
 }
-
-#register {
-    float: left;
-    display: inline-block;
-}
-
-h1 {
-    -webkit-border-radius: 4px;
-    -moz-border-radius: 4px;
-	background-color: #E9E9E9;
-	border: 1px solid #CFCFCF;
-	border-radius: 4px;
-}
-
-.nav li {
-    float: left;
-    list-style: none;
-    padding: 5px;
-}
-
-.navbar {
-    text-align: right;
-    padding: 5px;
-    margin-bottom: 10px;
-}
-
-#container {
-    height: auto;
-    margin-bottom: 10px;
-}
-
-#footer {    
-    width: 95%;
-    margin-left: 1%;
-    margin-right: 1%;
-    position:absolute;
-    bottom:0;
-    font-size: 11px;
-    font-weight: bold;
-    height: auto;    
-    text-align: center;
-    
-	padding-top: 10px;
-	
-	-webkit-border-radius: 4px;
-    -moz-border-radius: 4px;
-	background-color: #E9E9E9;
-	border: 1px solid #CFCFCF;
-	border-radius: 4px;
-}

+ 20 - 0
frameworks/Clojure/luminus/hello/resources/sql/queries.sql

@@ -0,0 +1,20 @@
+--name: get-world
+-- Query a World record from the database
+SELECT * FROM world
+WHERE id = :id
+
+--name: get-all-fortunes
+-- select all records from the fortune table
+SELECT * FROM fortune
+
+--name: update-world<!
+-- update an existing world record
+UPDATE world
+SET randomNumber = :randomNumber
+WHERE id = :id
+
+--name: get-all-fortunes
+-- query all fortune records
+SELECT id, message FROM fortune
+
+

+ 0 - 0
frameworks/Clojure/luminus/hello/src/hello/views/templates/base.html → frameworks/Clojure/luminus/hello/resources/templates/base.html


+ 3 - 3
frameworks/Clojure/luminus/hello/src/hello/views/templates/home.html → frameworks/Clojure/luminus/hello/resources/templates/home.html

@@ -1,4 +1,4 @@
-{% extends "hello/views/templates/base.html" %}
+{% extends "base.html" %}
 
 
 {% block content %}
 {% block content %}
 
 
@@ -13,6 +13,6 @@
     <td>{{message.message}}</td>
     <td>{{message.message}}</td>
   </tr>
   </tr>
   {% endfor %}
   {% endfor %}
-</table>  
-  
+</table>
+
 {% endblock %}
 {% endblock %}

+ 30 - 0
frameworks/Clojure/luminus/hello/src/hello/core.clj

@@ -0,0 +1,30 @@
+(ns hello.core
+  (:require [hello.handler :refer [app init]]
+            [clojure.tools.cli :refer [cli]]
+            [org.httpkit.server :refer [run-server]])
+  (:gen-class))
+
+(defn parse-port [s]
+  "Convert stringy port number int. Defaults to 8080."
+  (cond
+    (string? s) (Integer/parseInt s)
+    (instance? Integer s) s
+    (instance? Long s) (.intValue ^Long s)
+    :else 8080))
+
+(defn start-server [{:keys [port]}]
+  (let [cpu (.availableProcessors (Runtime/getRuntime))]
+    ;; double worker threads should increase database access performance
+    (init)
+    (run-server app {:port port :thread (* 2 cpu)})
+    (println (str "http-kit server listens at :" port))))
+
+(defn -main [& args]
+  (let [[options _ banner]
+        (cli args
+             ["-p" "--port" "Port to listen" :default 8080 :parse-fn parse-port]
+             ["--[no-]help" "Print this help"])]
+    (when (:help options)
+          (println banner)
+          (System/exit 0))
+    (start-server options)))

+ 69 - 0
frameworks/Clojure/luminus/hello/src/hello/db/core.clj

@@ -0,0 +1,69 @@
+(ns hello.db.core
+  (:require
+    [yesql.core :refer [defqueries]])
+  (:import com.mchange.v2.c3p0.ComboPooledDataSource))
+
+(def db-spec
+  {:classname "com.mysql.jdbc.Driver"
+   :subprotocol "mysql"
+   :subname "//localhost:3306/hello_world?jdbcCompliantTruncation=false&elideSetAutoCommits=true&useLocalSessionState=true&cachePrepStmts=true&cacheCallableStmts=true&alwaysSendSetIsolation=false&prepStmtCacheSize=4096&cacheServerConfiguration=true&prepStmtCacheSqlLimit=2048&zeroDateTimeBehavior=convertToNull&traceProtocol=false&useUnbufferedInput=false&useReadAheadInput=false&maintainTimeStats=false&useServerPrepStmts&cacheRSMetadata=true"
+   :user "benchmarkdbuser"
+   :password "benchmarkdbpass"})
+
+(defn pool
+  [spec]
+  {:datasource
+   (doto (ComboPooledDataSource.)
+     (.setDriverClass (:classname spec))
+     (.setJdbcUrl (str "jdbc:" (:subprotocol spec) ":" (:subname spec)))
+     (.setUser (:user spec))
+     (.setPassword (:password spec))
+     ;; expire excess connections after 30 minutes of inactivity:
+     (.setMaxIdleTimeExcessConnections (* 30 60))
+     ;; expire connections after 3 hours of inactivity:
+     (.setMaxIdleTime (* 3 60 60)))})
+
+(defonce db (atom nil))
+
+(defn connect! []
+  (reset! db (pool db-spec)))
+
+(defqueries "sql/queries.sql")
+
+(defn get-world-random
+  "Query a random World record between 1 and 10,000 from the database"
+  []
+  (get-world {:id (inc (rand-int 9999))} {:connection @db}))
+
+(defn get-query-count [queries]
+  "Parse provided string value of query count, clamping values to between 1 and 500."
+  (let [n (try (Integer/parseInt queries)
+               (catch Exception e 1))] ; default to 1 on parse failure
+    (cond
+      (< n 1) 1
+      (> n 500) 500
+      :else n)))
+
+(defn run-queries
+  "Run the specified number of queries, return the results"
+  [queries]
+  (flatten (repeatedly (get-query-count queries) get-world-random)))
+
+(defn get-fortunes []
+   "Fetch the full list of Fortunes from the database, sort them by the fortune
+  message text, and then return the results."
+  (sort-by
+   :message
+   (conj (get-all-fortunes {} {:connection @db})
+         {:id 0 :message "Additional fortune added at request time."})))
+
+(defn update-and-persist
+  "Changes the :randomNumber of a number of world entities.
+  Persists the changes to sql then returns the updated entities"
+  [queries]
+  (for [world (-> queries run-queries)]
+    (let [updated-world (assoc world :randomNumber (inc (rand-int 9999)))]
+      (update-world<! updated-world {:connection @db})
+      updated-world)))
+
+

+ 34 - 34
frameworks/Clojure/luminus/hello/src/hello/handler.clj

@@ -1,20 +1,20 @@
 (ns hello.handler
 (ns hello.handler
-  (:use hello.routes.home
-        compojure.core)
-  (:require [noir.util.middleware :as middleware]
+  (:require [compojure.core :refer [defroutes routes]]
+            [hello.routes.home :refer [home-routes]]
+            [hello.db.core :as db]
+            [hello.middleware
+             :refer [development-middleware production-middleware]]
+            [hello.session :as session]
             [compojure.route :as route]
             [compojure.route :as route]
             [taoensso.timbre :as timbre]
             [taoensso.timbre :as timbre]
-            [taoensso.timbre.appenders.rotor :as rotor]))
-
-
-(defroutes app-routes
-  (route/resources "/")
-  (route/not-found "Not Found"))
-
-
-(defn destroy []
-  (timbre/info "picture-gallery is shutting down"))
+            [taoensso.timbre.appenders.rotor :as rotor]
+            [selmer.parser :as parser]
+            [environ.core :refer [env]]
+            [cronj.core :as cronj]))
 
 
+(defroutes base-routes
+           (route/resources "/")
+           (route/not-found "Not Found"))
 
 
 (defn init
 (defn init
   "init will be called once when
   "init will be called once when
@@ -24,34 +24,34 @@
   []
   []
   (timbre/set-config!
   (timbre/set-config!
     [:appenders :rotor]
     [:appenders :rotor]
-    {:min-level :info
-     :enabled? true
-     :async? false ; should be always false for rotor
+    {:min-level             :info
+     :enabled?              true
+     :async?                false ; should be always false for rotor
      :max-message-per-msecs nil
      :max-message-per-msecs nil
-     :fn rotor/appender-fn})
+     :fn                    rotor/appender-fn})
 
 
   (timbre/set-config!
   (timbre/set-config!
     [:shared-appender-config :rotor]
     [:shared-appender-config :rotor]
-    {:path "{{sanitized}}.log" :max-size (* 512 1024) :backlog 10})
-
-  (timbre/info "hello started successfully"))
+    {:path "hello.log" :max-size (* 512 1024) :backlog 10})
 
 
+  (if (env :dev) (parser/cache-off!))
+  (db/connect!)
+  ;;start the expired session cleanup job
+  (cronj/start! session/cleanup-job)
+  (timbre/info "\n-=[ hello started successfully"
+               (when (env :dev) "using the development profile") "]=-"))
 
 
 (defn destroy
 (defn destroy
   "destroy will be called when your application
   "destroy will be called when your application
    shuts down, put any clean up code here"
    shuts down, put any clean up code here"
   []
   []
-  (timbre/info "hello is shutting down..."))
-
-
-(def app (middleware/app-handler
-           ;; add your application routes here
-           [home-routes app-routes]
-           ;; add custom middleware here
-           :middleware []
-           ;; add access rules here
-           :access-rules []
-           ;; serialize/deserialize the following data formats
-           ;; available formats:
-           ;; :json :json-kw :yaml :yaml-kw :edn :yaml-in-html
-           :formats [:json-kw :edn]))
+  (timbre/info "hello is shutting down...")
+  (cronj/shutdown! session/cleanup-job)
+  (timbre/info "shutdown complete!"))
+
+(def app
+  (-> (routes
+        home-routes
+        base-routes)
+      development-middleware
+      production-middleware))

+ 37 - 0
frameworks/Clojure/luminus/hello/src/hello/layout.clj

@@ -0,0 +1,37 @@
+(ns hello.layout
+  (:require [selmer.parser :as parser]
+            [selmer.filters :as filters]
+            [markdown.core :refer [md-to-html-string]]
+            [ring.util.response :refer [content-type response]]
+            [compojure.response :refer [Renderable]]
+            [ring.util.anti-forgery :refer [anti-forgery-field]]
+            [ring.middleware.anti-forgery :refer [*anti-forgery-token*]]
+            [environ.core :refer [env]]))
+
+(parser/set-resource-path!  (clojure.java.io/resource "templates"))
+
+(parser/add-tag! :csrf-field (fn [_ _] (anti-forgery-field)))
+(filters/add-filter! :markdown (fn [content] [:safe (md-to-html-string content)]))
+
+(deftype RenderableTemplate [template params]
+  Renderable
+  (render [this request]
+    (content-type
+      (->> (assoc params
+                  :page template
+                  :dev (env :dev)
+                  :csrf-token *anti-forgery-token*
+                  :servlet-context
+                  (if-let [context (:servlet-context request)]
+                    ;; If we're not inside a serlvet environment (for
+                    ;; example when using mock requests), then
+                    ;; .getContextPath might not exist
+                    (try (.getContextPath context)
+                         (catch IllegalArgumentException _ context))))
+        (parser/render-file (str template))
+        response)
+      "text/html; charset=utf-8")))
+
+(defn render [template & [params]]
+  (RenderableTemplate. template params))
+

+ 37 - 0
frameworks/Clojure/luminus/hello/src/hello/middleware.clj

@@ -0,0 +1,37 @@
+(ns hello.middleware
+  (:require [hello.session :as session]
+            [taoensso.timbre :as timbre]
+            [environ.core :refer [env]]
+            [selmer.middleware :refer [wrap-error-page]]
+            [prone.middleware :refer [wrap-exceptions]]
+            [ring.util.response :refer [redirect]]
+            [ring.middleware.defaults :refer [site-defaults wrap-defaults]]
+            [ring.middleware.session-timeout :refer [wrap-idle-session-timeout]]
+            [noir-exception.core :refer [wrap-internal-error]]
+            [ring.middleware.session.memory :refer [memory-store]]
+            [ring.middleware.format :refer [wrap-restful-format]]
+            
+            ))
+
+(defn log-request [handler]
+  (fn [req]
+    (timbre/debug req)
+    (handler req)))
+
+(defn development-middleware [handler]
+  (if (env :dev)
+    (-> handler
+        wrap-error-page
+        wrap-exceptions)
+    handler))
+
+(defn production-middleware [handler]
+  (-> handler
+      
+      (wrap-restful-format :formats [:json-kw :edn :transit-json :transit-msgpack])
+      (wrap-idle-session-timeout
+        {:timeout (* 60 30)
+         :timeout-response (redirect "/")})
+      (wrap-defaults
+        (assoc-in site-defaults [:session :store] (memory-store session/mem)))
+      (wrap-internal-error :log #(timbre/error %))))

+ 0 - 94
frameworks/Clojure/luminus/hello/src/hello/models/db.clj

@@ -1,94 +0,0 @@
-(ns hello.models.db
-  (:use korma.core
-         hello.models.schema)
-  (:require [clojure.java.jdbc :as jdbc]))
-
-
-
-; Set up entity World and the database representation
-(defentity world
-  (pk :id)
-  (table :world)
-  (entity-fields :id :randomNumber)
-  (database db))
-
-
-(defn get-world
-  "Query a random World record from the database"
-  []
-  (let [id (inc (rand-int 9999))] ; Num between 1 and 10,000
-    (select world
-            (fields :id :randomNumber)
-            (where {:id id }))))
-
-
-(defn get-world-raw
-  "Query a random World record from the database"
-  []
-  (let [id (inc (rand-int 9999))] ; Num between 1 and 10,000
-    (jdbc/with-connection (db-raw)
-      ; Set a naming strategy to preserve column name case
-      (jdbc/with-naming-strategy {:keyword identity}
-        (jdbc/with-query-results rs [(str "select * from world where id = ?") id]
-          (doall rs))))))
-
-
-(defn run-queries
-  "Run the specified number of queries, return the results"
-  [queries]
-  (flatten ; Make it a list of maps
-    (take queries
-          (repeatedly get-world))))
-
-
-(defn run-queries-raw [queries]
-  "Run the specified number of queries, return the results"
-  (flatten ; Make it a list of maps
-    (take queries
-          (repeatedly get-world-raw))))
-
-
-(defn get-query-count [queries]
-  "Parse provided string value of query count, clamping values to between 1 and 500."
-  (let [q (try (Integer/parseInt queries)
-               (catch Exception e 1))] ; default to 1 on parse failure
-    (if (> q 500)
-      500 ; clamp to 500 max
-      (if (< q 1)
-        1 ; clamp to 1 min
-        q)))) ; otherwise use provided value
-
-
-; Set up entity World and the database representation
-(defentity fortune
-  (pk :id)
-  (table :fortune)
-  (entity-fields :id :message)
-  (database db))
-
-
-(def get-all-fortunes
-  "Query all Fortune records from the database."
-  (select fortune
-          (fields :id :message)))
-
-
-(def get-fortunes
-  "Fetch the full list of Fortunes from the database. Insert an additional fortune at runtime.
-  Then sort all by fortune message text. Return the results."
-  (let [fortunes (conj get-all-fortunes
-                       {:id 0 :message "Additional fortune added at request time."})]
-    (sort-by :message fortunes)))
-
-
-(defn update-and-persist
-  "Changes the :randomNumber of a number of world entities.
-  Persists the changes to sql then returns the updated entities"
-  [queries]
-  (let [results (run-queries queries)]
-    (for [w results]
-      (update-in w [:randomNumber (inc (rand-int 9999))]
-        (update world
-                (set-fields {:randomNumber (:randomNumber w)})
-                (where {:id [:id w]}))))
-    results))

+ 0 - 39
frameworks/Clojure/luminus/hello/src/hello/models/schema.clj

@@ -1,39 +0,0 @@
-(ns hello.models.schema
-  (:require [korma.db :refer [defdb mysql]]
-            [clojure.java.jdbc :as sql])
-  (:import com.mchange.v2.c3p0.ComboPooledDataSource))
-
-; Database connection for java.jdbc "raw"
-; https://github.com/clojure/java.jdbc/blob/master/doc/clojure/java/jdbc/ConnectionPooling.md
-(def db-spec-mysql-raw
-  {:classname "com.mysql.jdbc.Driver"
-   :subprotocol "mysql"
-   :subname "//localhost:3306/hello_world?jdbcCompliantTruncation=false&elideSetAutoCommits=true&useLocalSessionState=true&cachePrepStmts=true&cacheCallableStmts=true&alwaysSendSetIsolation=false&prepStmtCacheSize=4096&cacheServerConfiguration=true&prepStmtCacheSqlLimit=2048&zeroDateTimeBehavior=convertToNull&traceProtocol=false&useUnbufferedInput=false&useReadAheadInput=false&maintainTimeStats=false&useServerPrepStmts&cacheRSMetadata=true"
-   :user "benchmarkdbuser"
-   :password "benchmarkdbpass"})
-
-; Database connection
-(defdb db (mysql {:subname "//localhost:3306/hello_world?jdbcCompliantTruncation=false&elideSetAutoCommits=true&useLocalSessionState=true&cachePrepStmts=true&cacheCallableStmts=true&alwaysSendSetIsolation=false&prepStmtCacheSize=4096&cacheServerConfiguration=true&prepStmtCacheSqlLimit=2048&zeroDateTimeBehavior=convertToNull&traceProtocol=false&useUnbufferedInput=false&useReadAheadInput=false&maintainTimeStats=false&useServerPrepStmts&cacheRSMetadata=true"
-                  :user "benchmarkdbuser"
-                  :password "benchmarkdbpass"
-                  ;;OPTIONAL KEYS
-                  :delimiters "" ;; remove delimiters
-                  :maximum-pool-size 256
-                  }))
-                  
-(defn pool
-  [spec]
-  (let [cpds (doto (ComboPooledDataSource.)
-               (.setDriverClass (:classname spec))
-               (.setJdbcUrl (str "jdbc:" (:subprotocol spec) ":" (:subname spec)))
-               (.setUser (:user spec))
-               (.setPassword (:password spec))
-               ;; expire excess connections after 30 minutes of inactivity:
-               (.setMaxIdleTimeExcessConnections (* 30 60))
-               ;; expire connections after 3 hours of inactivity:
-               (.setMaxIdleTime (* 3 60 60)))]
-    {:datasource cpds}))
-
-(def pooled-db (delay (pool db-spec-mysql-raw)))
-
-(defn db-raw [] @pooled-db)

+ 24 - 50
frameworks/Clojure/luminus/hello/src/hello/routes/home.clj

@@ -1,75 +1,49 @@
 (ns hello.routes.home
 (ns hello.routes.home
-  (:use compojure.core
-        hello.models.db)
-  (:require [hello.views.layout :as layout]
-            [noir.response :as response]))
-
+  (:require [hello.layout :as layout]
+            [hello.db.core :as db]
+            [compojure.core :refer [defroutes GET]]
+            [ring.util.response :refer [response]]
+            [clojure.java.io :as io]))
 
 
 (def json-serialization
 (def json-serialization
   "Test 1: JSON serialization"
   "Test 1: JSON serialization"
-  (response/json {:message "Hello, World!"}))
-
+  (response {:message "Hello, World!"}))
 
 
-(def single-query-test
+(defn single-query-test
   "Test 2: Single database query"
   "Test 2: Single database query"
-  (response/json (first (run-queries 1))))
-
+  []
+  (-> 1 db/run-queries first response))
 
 
 (defn multiple-query-test
 (defn multiple-query-test
   "Test 3: Multiple database query"
   "Test 3: Multiple database query"
   [queries]
   [queries]
   (-> queries
   (-> queries
-      (get-query-count)
-      (run-queries)
-      (response/json)))
-
+      db/run-queries
+      response))
 
 
-(def single-query-test-raw
-  "Test 2: Single database query (raw)"
-  (-> 1
-      (run-queries-raw)
-      (first)
-      (response/json)))
-
-
-(defn multiple-query-test-raw
-  "Test 3: Multiple database query (raw)"
-  [queries]
-  (-> queries
-      (get-query-count)
-      (run-queries-raw)
-      (response/json)))
-
-
-(def fortunes
+(defn fortunes
   "Test 4: Fortunes"
   "Test 4: Fortunes"
-  (layout/render "home.html"
-                 {:messages get-fortunes}))
-
+  []
+  (layout/render "home.html" {:messages (db/get-fortunes)}))
 
 
 (defn db-update
 (defn db-update
   "Test 5: Database updates"
   "Test 5: Database updates"
   [queries]
   [queries]
   (-> queries
   (-> queries
-      (get-query-count)
-      (update-and-persist)
-      (response/json)))
-
+      db/update-and-persist
+      response))
 
 
 (def plaintext
 (def plaintext
   "Test 6: Plaintext"
   "Test 6: Plaintext"
   {:status 200
   {:status 200
-   :headers {"Content-Type" "text/plain; charset=utf-8"}
+   :headers {"Content-Type" "text/plain"}
    :body "Hello, World!"})
    :body "Hello, World!"})
 
 
-
 (defroutes home-routes
 (defroutes home-routes
-  (GET "/"                [] "Hello, World!")
-  (GET "/plaintext"       [] plaintext)
-  (GET "/json"            [] json-serialization)
-  (GET "/db"              [] single-query-test)
-  (GET "/db/:queries"     [queries] (multiple-query-test queries))
-  (GET "/dbraw"           [] single-query-test-raw)
-  (GET "/dbraw/:queries"  [queries] (multiple-query-test-raw queries))
-  (GET "/fortune"         [] fortunes)
-  (GET "/update/:queries" [queries] (db-update queries)))
+  (GET "/"                 [] "Hello, World!")
+  (GET "/plaintext"        [] plaintext)
+  (GET "/json"             [] json-serialization)
+  (GET "/db"               [] (single-query-test))
+  (GET "/queries/:queries" [queries] (multiple-query-test queries))
+  (GET "/fortunes"         [] (fortunes))
+  (GET "/updates/:queries"  [queries] (db-update queries)))

+ 21 - 0
frameworks/Clojure/luminus/hello/src/hello/session.clj

@@ -0,0 +1,21 @@
+(ns hello.session
+  (:require [cronj.core :refer [cronj]]))
+
+(defonce mem (atom {}))
+
+(defn- current-time []
+  (quot (System/currentTimeMillis) 1000))
+
+(defn- expired? [[id session]]
+  (pos? (- (:ring.middleware.session-timeout/idle-timeout session) (current-time))))
+
+(defn clear-expired-sessions []
+  (clojure.core/swap! mem #(->> % (filter expired?) (into {}))))
+
+(def cleanup-job
+  (cronj
+    :entries
+    [{:id "session-cleanup"
+      :handler (fn [_ _] (clear-expired-sessions))
+      :schedule "* /30 * * * * *"
+      :opts {}}]))

+ 0 - 10
frameworks/Clojure/luminus/hello/src/hello/views/layout.clj

@@ -1,10 +0,0 @@
-(ns hello.views.layout
-  (:use noir.request)
-  (:require [selmer.parser :as parser]))
-
-(def template-path "hello/views/templates/")
-
-(defn render [template & [params]]
-  (parser/render-file (str template-path template)
-                      (assoc params :context (:context *request*))))
-

+ 2 - 4
frameworks/Clojure/luminus/hello/test/hello/test/handler.clj

@@ -6,10 +6,8 @@
 (deftest test-app
 (deftest test-app
   (testing "main route"
   (testing "main route"
     (let [response (app (request :get "/"))]
     (let [response (app (request :get "/"))]
-      (is (= (:status response) 200))
-      (is (= (:body response)
-             "Hello, World!"))))
+      (is (= 200 (:status response)))))
 
 
   (testing "not-found route"
   (testing "not-found route"
     (let [response (app (request :get "/invalid"))]
     (let [response (app (request :get "/invalid"))]
-      (is (= (:status response) 404)))))
+      (is (= 404 (:status response))))))

+ 6 - 12
frameworks/Clojure/luminus/setup.sh

@@ -1,19 +1,13 @@
 #!/bin/bash
 #!/bin/bash
-
 source $IROOT/java7.installed
 source $IROOT/java7.installed
-
 source $IROOT/lein.installed
 source $IROOT/lein.installed
 
 
-export RESIN_HOME=${IROOT}/resin-4.0.41
-
-# Path vars must be set here
-export PATH="$JAVA_HOME/bin:$PATH"
-
-sed -i 's|:subname "//.*:3306|:subname "//'"${DBHOST}"':3306|g' hello/src/hello/models/schema.clj
+# Update db host in the source file
+sed -i 's|:subname "//.*:3306|:subname "//'"${DBHOST}"':3306|g' hello/src/hello/db/core.clj
 
 
 cd hello
 cd hello
 lein clean
 lein clean
-lein ring uberwar
-rm -rf $RESIN_HOME/webapps/*
-cp target/hello-luminus-standalone.war $RESIN_HOME/webapps/luminus.war
-$RESIN_HOME/bin/resinctl start
+rm -rf target
+# pack all dependencies into a single jar: target/http-kit-standalone.jar
+lein uberjar
+java -server -jar target/hello.jar  &

+ 23 - 14
frameworks/Clojure/luminus/source_code

@@ -1,23 +1,32 @@
+./luminus/hello/Procfile
+./luminus/hello/README.md
 ./luminus/hello/project.clj
 ./luminus/hello/project.clj
-./luminus/hello/src/
-./luminus/hello/src/log4j.xml
-./luminus/hello/src/hello
-./luminus/hello/src/hello/routes
-./luminus/hello/src/hello/routes/home.clj
-./luminus/hello/src/hello/views
-./luminus/hello/src/hello/views/templates
-./luminus/hello/src/hello/views/templates/base.html
-./luminus/hello/src/hello/views/templates/home.html
-./luminus/hello/src/hello/views/layout.clj
-./luminus/hello/src/hello/handler.clj
-./luminus/hello/src/hello/models
-./luminus/hello/src/hello/models/schema.clj
-./luminus/hello/src/hello/models/db.clj
+./luminus/hello/env/
+./luminus/hello/env/dev/clj
+./luminus/hello/env/dev/clj/hello
+./luminus/hello/env/dev/clj/hello/repl.clj
 ./luminus/hello/resources/
 ./luminus/hello/resources/
 ./luminus/hello/resources/public
 ./luminus/hello/resources/public
 ./luminus/hello/resources/public/css
 ./luminus/hello/resources/public/css
 ./luminus/hello/resources/public/css/screen.css
 ./luminus/hello/resources/public/css/screen.css
+./luminus/hello/resources/sql
+./luminus/hello/resources/sql/queries.sql
+./luminus/hello//resources/templates
+./luminus/hello//resources/templates/base.html
+./luminus/hello//resources/templates/home.html
+./luminus/hello/src/
+./luminus/hello/src/hello
+./luminus/hello/src/hello/core.clj
+./luminus/hello/src/hello/handler.clj
+./luminus/hello/src/hello/layout.clj
+./luminus/hello/src/hello/middleware.clj
+./luminus/hello/src/hello/session.clj
+./luminus/hello/src/hello/db
+./luminus/hello/src/hello/db/core.clj
+./luminus/hello/src/hello/routes
+./luminus/hello/src/hello/routes/home.clj
 ./luminus/hello/test/
 ./luminus/hello/test/
 ./luminus/hello/test/hello
 ./luminus/hello/test/hello
 ./luminus/hello/test/hello/test
 ./luminus/hello/test/hello/test
 ./luminus/hello/test/hello/test/handler.clj
 ./luminus/hello/test/hello/test/handler.clj
+

+ 2 - 2
frameworks/Java/netty/pom.xml

@@ -13,12 +13,12 @@
 		<dependency>
 		<dependency>
 			<groupId>io.netty</groupId>
 			<groupId>io.netty</groupId>
 			<artifactId>netty-codec-http</artifactId>
 			<artifactId>netty-codec-http</artifactId>
-			<version>4.0.26.Final</version>
+			<version>4.0.28.Final</version>
 		</dependency>
 		</dependency>
 		<dependency>
 		<dependency>
 			<groupId>io.netty</groupId>
 			<groupId>io.netty</groupId>
 			<artifactId>netty-transport-native-epoll</artifactId>
 			<artifactId>netty-transport-native-epoll</artifactId>
-			<version>4.0.26.Final</version>
+			<version>4.0.28.Final</version>
 			<classifier>linux-x86_64</classifier>
 			<classifier>linux-x86_64</classifier>
 		</dependency>
 		</dependency>
 		<dependency>
 		<dependency>

+ 1 - 1
frameworks/Java/play2-java/install.sh

@@ -1,3 +1,3 @@
 #!/bin/bash
 #!/bin/bash
 
 
-fw_depends java7 sbt
+fw_depends java8 sbt

+ 2 - 2
frameworks/Java/play2-java/play2-java-ebean-bonecp/build.sbt

@@ -4,10 +4,10 @@ version := "1.0-SNAPSHOT"
 
 
 lazy val root = (project in file(".")).enablePlugins(PlayJava)
 lazy val root = (project in file(".")).enablePlugins(PlayJava)
 
 
-scalaVersion := "2.11.4"
+scalaVersion := "2.11.6"
 
 
 libraryDependencies ++= Seq(
 libraryDependencies ++= Seq(
   javaJdbc,
   javaJdbc,
   javaEbean,
   javaEbean,
-  "mysql" % "mysql-connector-java" % "5.1.33"
+  "mysql" % "mysql-connector-java" % "5.1.35"
 )
 )

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

@@ -5,4 +5,4 @@ logLevel := Level.Warn
 resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
 resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
 
 
 // Use the Play sbt plugin for Play projects
 // Use the Play sbt plugin for Play projects
-addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.7")
+addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.9")

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

@@ -4,13 +4,13 @@ version := "1.0-SNAPSHOT"
 
 
 lazy val root = (project in file(".")).enablePlugins(PlayJava)
 lazy val root = (project in file(".")).enablePlugins(PlayJava)
 
 
-scalaVersion := "2.11.4"
+scalaVersion := "2.11.6"
 
 
 libraryDependencies ++= Seq(
 libraryDependencies ++= Seq(
   javaJdbc,
   javaJdbc,
   javaEbean,
   javaEbean,
-  "mysql" % "mysql-connector-java" % "5.1.33",
-  "com.edulify" %% "play-hikaricp" % "1.5.0"
+  "mysql" % "mysql-connector-java" % "5.1.35",
+  "com.edulify" %% "play-hikaricp" % "2.0.4"
 )
 )
 
 
 resolvers += Resolver.url("Edulify Repository", url("http://edulify.github.io/modules/releases/"))(Resolver.ivyStylePatterns)
 resolvers += Resolver.url("Edulify Repository", url("http://edulify.github.io/modules/releases/"))(Resolver.ivyStylePatterns)

+ 46 - 18
frameworks/Java/play2-java/play2-java-ebean-hikaricp/conf/application.conf

@@ -29,25 +29,53 @@ application.langs="en"
 #
 #
 # You can expose this datasource via JNDI if needed (Useful for JPA)
 # You can expose this datasource via JNDI if needed (Useful for JPA)
 # db.default.jndiName=DefaultDS
 # db.default.jndiName=DefaultDS
-db.default.driver= com.mysql.jdbc.Driver
-db.default.url="jdbc:mysql://127.0.0.1:3306/hello_world?jdbcCompliantTruncation=false&elideSetAutoCommits=true&useLocalSessionState=true&cachePrepStmts=true&cacheCallableStmts=true&alwaysSendSetIsolation=false&prepStmtCacheSize=4096&cacheServerConfiguration=true&prepStmtCacheSqlLimit=2048&zeroDateTimeBehavior=convertToNull&traceProtocol=false&useUnbufferedInput=false&useReadAheadInput=false&maintainTimeStats=false&useServerPrepStmts&cacheRSMetadata=true"
-db.default.user=benchmarkdbuser
-db.default.password=benchmarkdbpass
-db.default.jndiName=DefaultDS
 
 
-db.default.partitionCount=4
-
-# The number of connections to create per partition. Setting this to 
-# 5 with 3 partitions means you will have 15 unique connections to the 
-# database.
-
-# This value maps to the maximumPoolSize for HickariCP (db.default.partitionCount * db.default.maxConnectionsPerPartition)
-db.default.maxConnectionsPerPartition=64
-
-# The number of initial connections, per partition.
-#
-# This maps to the minimumIdle connections for HikariCP (db.default.partitionCount * db.default.minConnectionsPerPartition)
-db.default.minConnectionsPerPartition=64
+db {
+  default {
+
+    jndiName="DefaultDS"
+
+    dataSourceClassName=com.mysql.jdbc.jdbc2.optional.MysqlDataSource
+    dataSource {
+      user=benchmarkdbuser
+      password=benchmarkdbpass
+      databaseName=hello_world
+      serverName=127.0.0.1
+      port=3306
+
+      jdbcCompliantTruncation=false
+      elideSetAutoCommits=true
+      useLocalSessionState=true
+      cachePrepStmts=true
+      cacheCallableStmts=true
+      cacheServerConfiguration=true
+      cacheResultSetMetadata=true
+      alwaysSendSetIsolation=false
+      prepStmtCacheSize=4096
+      prepStmtCacheSqlLimit=2048
+      zeroDateTimeBehavior=convertToNull
+      traceProtocol=false
+      useUnbufferedInput=false
+      useReadAheadInput=false
+      maintainTimeStats=false
+      useServerPrepStmts=true
+    }
+
+    partitionCount=4
+
+    # The number of connections to create per partition. Setting this to
+    # 5 with 3 partitions means you will have 15 unique connections to the
+    # database.
+
+    # This value maps to the maximumPoolSize for HickariCP (db.default.partitionCount * db.default.maxConnectionsPerPartition)
+    maxConnectionsPerPartition=64
+
+    # The number of initial connections, per partition.
+    #
+    # This maps to the minimumIdle connections for HikariCP (db.default.partitionCount * db.default.minConnectionsPerPartition)
+    minConnectionsPerPartition=64
+  }
+}
 
 
 dbplugin=disabled
 dbplugin=disabled
 
 

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

@@ -5,4 +5,4 @@ logLevel := Level.Warn
 resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
 resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
 
 
 // Use the Play sbt plugin for Play projects
 // Use the Play sbt plugin for Play projects
-addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.7")
+addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.9")

+ 3 - 3
frameworks/Java/play2-java/play2-java-jpa-bonecp/build.sbt

@@ -2,15 +2,15 @@ name := "play2-java-jpa-bonecp"
 
 
 version := "1.0-SNAPSHOT"
 version := "1.0-SNAPSHOT"
 
 
-scalaVersion := "2.11.4"
+scalaVersion := "2.11.6"
 
 
 lazy val root = (project in file(".")).enablePlugins(PlayJava)
 lazy val root = (project in file(".")).enablePlugins(PlayJava)
 
 
 libraryDependencies ++= Seq(
 libraryDependencies ++= Seq(
   javaJdbc,
   javaJdbc,
   javaJpa,
   javaJpa,
-  "mysql" % "mysql-connector-java" % "5.1.33",
-  "org.hibernate" % "hibernate-entitymanager" % "4.3.6.Final"
+  "mysql" % "mysql-connector-java" % "5.1.35",
+  "org.hibernate" % "hibernate-entitymanager" % "4.3.9.Final"
   )
   )
 
 
 dependencyOverrides += "com.jolbox" % "bonecp" % "0.8.0.RELEASE"
 dependencyOverrides += "com.jolbox" % "bonecp" % "0.8.0.RELEASE"

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

@@ -5,4 +5,4 @@ logLevel := Level.Warn
 resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
 resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
 
 
 // Use the Play sbt plugin for Play projects
 // Use the Play sbt plugin for Play projects
-addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.7")
+addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.9")

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

@@ -4,14 +4,14 @@ version := "1.0-SNAPSHOT"
 
 
 lazy val root = (project in file(".")).enablePlugins(PlayJava)
 lazy val root = (project in file(".")).enablePlugins(PlayJava)
 
 
-scalaVersion := "2.11.4"
+scalaVersion := "2.11.6"
 
 
 libraryDependencies ++= Seq(
 libraryDependencies ++= Seq(
   javaJdbc,
   javaJdbc,
   javaJpa,
   javaJpa,
-  "mysql" % "mysql-connector-java" % "5.1.33",
-  "org.hibernate" % "hibernate-entitymanager" % "4.3.6.Final",
-  "com.edulify" %% "play-hikaricp" % "1.5.0"
+  "mysql" % "mysql-connector-java" % "5.1.35",
+  "org.hibernate" % "hibernate-entitymanager" % "4.3.9.Final",
+  "com.edulify" %% "play-hikaricp" % "2.0.4"
 )
 )
 
 
 resolvers += Resolver.url("Edulify Repository", url("http://edulify.github.io/modules/releases/"))(Resolver.ivyStylePatterns)
 resolvers += Resolver.url("Edulify Repository", url("http://edulify.github.io/modules/releases/"))(Resolver.ivyStylePatterns)

+ 47 - 19
frameworks/Java/play2-java/play2-java-jpa-hikaricp/conf/application.conf

@@ -44,26 +44,54 @@ application.langs="en"
 # You can expose this datasource via JNDI if needed (Useful for JPA)
 # You can expose this datasource via JNDI if needed (Useful for JPA)
 # db.default.jndiName=DefaultDS
 # db.default.jndiName=DefaultDS
 
 
-db.default.driver= com.mysql.jdbc.Driver
-db.default.url="jdbc:mysql://127.0.0.1:3306/hello_world?jdbcCompliantTruncation=false&elideSetAutoCommits=true&useLocalSessionState=true&cachePrepStmts=true&cacheCallableStmts=true&alwaysSendSetIsolation=false&prepStmtCacheSize=4096&cacheServerConfiguration=true&prepStmtCacheSqlLimit=2048&zeroDateTimeBehavior=convertToNull&traceProtocol=false&useUnbufferedInput=false&useReadAheadInput=false&maintainTimeStats=false&useServerPrepStmts&cacheRSMetadata=true"
-db.default.user=benchmarkdbuser
-db.default.password=benchmarkdbpass
-db.default.jndiName=DefaultDS
-jpa.default=defaultPersistenceUnit
-
-db.default.partitionCount=4
-
-# The number of connections to create per partition. Setting this to
-# 5 with 3 partitions means you will have 15 unique connections to the
-# database..
-#
-# This value maps to the maximumPoolSize for HickariCP (db.default.partitionCount * db.default.maxConnectionsPerPartition)
-db.default.maxConnectionsPerPartition=64
+db {
+  default {
+
+    jndiName="DefaultDS"
+
+    dataSourceClassName=com.mysql.jdbc.jdbc2.optional.MysqlDataSource
+    dataSource {
+      user=benchmarkdbuser
+      password=benchmarkdbpass
+      databaseName=hello_world
+      serverName=127.0.0.1
+      port=3306
+
+      jdbcCompliantTruncation=false
+      elideSetAutoCommits=true
+      useLocalSessionState=true
+      cachePrepStmts=true
+      cacheCallableStmts=true
+      cacheServerConfiguration=true
+      cacheResultSetMetadata=true
+      alwaysSendSetIsolation=false
+      prepStmtCacheSize=4096
+      prepStmtCacheSqlLimit=2048
+      zeroDateTimeBehavior=convertToNull
+      traceProtocol=false
+      useUnbufferedInput=false
+      useReadAheadInput=false
+      maintainTimeStats=false
+      useServerPrepStmts=true
+    }
+
+    partitionCount=4
+
+    # The number of connections to create per partition. Setting this to
+    # 5 with 3 partitions means you will have 15 unique connections to the
+    # database.
+
+    # This value maps to the maximumPoolSize for HickariCP (db.default.partitionCount * db.default.maxConnectionsPerPartition)
+    maxConnectionsPerPartition=64
+
+    # The number of initial connections, per partition.
+    #
+    # This maps to the minimumIdle connections for HikariCP (db.default.partitionCount * db.default.minConnectionsPerPartition)
+    minConnectionsPerPartition=64
+  }
+}
 
 
-# The number of initial connections, per partition.
-#
-# This maps to the minimumIdle connections for HikariCP (db.default.partitionCount * db.default.minConnectionsPerPartition)
-db.default.minConnectionsPerPartition=64
+jpa.default=defaultPersistenceUnit
 
 
 dbplugin=disabled
 dbplugin=disabled
 
 

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

@@ -1,4 +1,4 @@
 resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
 resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
 
 
 // The Play plugin
 // The Play plugin
-addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.7")
+addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.9")

+ 1 - 1
frameworks/Java/play2-java/play2-java/build.sbt

@@ -4,4 +4,4 @@ version := "1.0-SNAPSHOT"
 
 
 lazy val root = (project in file(".")).enablePlugins(PlayJava)
 lazy val root = (project in file(".")).enablePlugins(PlayJava)
 
 
-scalaVersion := "2.11.4"
+scalaVersion := "2.11.6"

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

@@ -5,4 +5,4 @@ logLevel := Level.Warn
 resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
 resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
 
 
 // Use the Play sbt plugin for Play projects
 // Use the Play sbt plugin for Play projects
-addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.7")
+addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.9")

+ 1 - 1
frameworks/Java/play2-java/setup_java.sh

@@ -1,7 +1,7 @@
 #!/bin/bash
 #!/bin/bash
 
 
 # load java environment variables
 # load java environment variables
-source $IROOT/java7.installed
+source $IROOT/java8.installed
 
 
 cd play2-java
 cd play2-java
 
 

+ 1 - 1
frameworks/Java/play2-java/setup_java_ebean_bonecp.sh

@@ -1,7 +1,7 @@
 #!/bin/bash
 #!/bin/bash
 
 
 # load java environment variables
 # load java environment variables
-source $IROOT/java7.installed
+source $IROOT/java8.installed
 
 
 cd play2-java-ebean-bonecp
 cd play2-java-ebean-bonecp
 
 

+ 1 - 1
frameworks/Java/play2-java/setup_java_ebean_hikaricp.sh

@@ -1,7 +1,7 @@
 #!/bin/bash
 #!/bin/bash
 
 
 # load java environment variables
 # load java environment variables
-source $IROOT/java7.installed
+source $IROOT/java8.installed
 
 
 cd play2-java-ebean-hikaricp
 cd play2-java-ebean-hikaricp
 
 

+ 1 - 1
frameworks/Java/play2-java/setup_java_jpa_bonecp.sh

@@ -1,7 +1,7 @@
 #!/bin/bash
 #!/bin/bash
 
 
 # load java environment variables
 # load java environment variables
-source $IROOT/java7.installed
+source $IROOT/java8.installed
 
 
 cd play2-java-jpa-bonecp
 cd play2-java-jpa-bonecp
 
 

+ 1 - 1
frameworks/Java/play2-java/setup_java_jpa_hikaricp.sh

@@ -1,7 +1,7 @@
 #!/bin/bash
 #!/bin/bash
 
 
 # load java environment variables
 # load java environment variables
-source $IROOT/java7.installed
+source $IROOT/java8.installed
 
 
 cd play2-java-jpa-hikaricp
 cd play2-java-jpa-hikaricp
 
 

+ 78 - 2
frameworks/Java/sabina/benchmark_config.json

@@ -8,8 +8,59 @@
       "fortune_url": "/fortune",
       "fortune_url": "/fortune",
       "update_url": "/update?queries=",
       "update_url": "/update?queries=",
       "plaintext_url": "/plaintext",
       "plaintext_url": "/plaintext",
+
       "port": 5050,
       "port": 5050,
-      "setup_file": "setup",
+      "setup_file": "undertow-mongodb",
+      "approach": "Realistic",
+      "classification": "Micro",
+      "database": "MongoDB",
+      "framework": "Sabina",
+      "language": "Java",
+      "orm": "Raw",
+      "platform": "Servlet",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "Sabina Undertow MongoDB",
+      "notes": "",
+      "versus": "servlet"
+    }
+  }, {
+    "undertow-mysql": {
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/query?queries=",
+      "fortune_url": "/fortune",
+      "update_url": "/update?queries=",
+      "plaintext_url": "/plaintext",
+
+      "port": 5050,
+      "setup_file": "undertow",
+      "approach": "Realistic",
+      "classification": "Micro",
+      "database": "MySQL",
+      "framework": "Sabina",
+      "language": "Java",
+      "orm": "Raw",
+      "platform": "Servlet",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "Sabina Undertow MySQL",
+      "notes": "",
+      "versus": "servlet"
+    }
+  }, {
+    "jetty-mysql": {
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/query?queries=",
+      "fortune_url": "/fortune",
+      "update_url": "/update?queries=",
+      "plaintext_url": "/plaintext",
+
+      "port": 5050,
+      "setup_file": "jetty",
       "approach": "Realistic",
       "approach": "Realistic",
       "classification": "Micro",
       "classification": "Micro",
       "database": "MySQL",
       "database": "MySQL",
@@ -20,7 +71,32 @@
       "webserver": "None",
       "webserver": "None",
       "os": "Linux",
       "os": "Linux",
       "database_os": "Linux",
       "database_os": "Linux",
-      "display_name": "Sabina",
+      "display_name": "Sabina Jetty MySQL",
+      "notes": "",
+      "versus": "servlet"
+    }
+  }, {
+    "jetty-mongodb": {
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/query?queries=",
+      "fortune_url": "/fortune",
+      "update_url": "/update?queries=",
+      "plaintext_url": "/plaintext",
+
+      "port": 5050,
+      "setup_file": "jetty-mongodb",
+      "approach": "Realistic",
+      "classification": "Micro",
+      "database": "MongoDB",
+      "framework": "Sabina",
+      "language": "Java",
+      "orm": "Raw",
+      "platform": "Servlet",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "Sabina Jetty MongoDB",
       "notes": "",
       "notes": "",
       "versus": "servlet"
       "versus": "servlet"
     }
     }

+ 3 - 0
frameworks/Java/sabina/jetty-mongodb.sh

@@ -0,0 +1,3 @@
+#!/bin/bash
+
+./setup.sh -Dsabina.backend=jetty -Dsabina.benchmark.repository=mongodb

+ 3 - 0
frameworks/Java/sabina/jetty.sh

@@ -0,0 +1,3 @@
+#!/bin/bash
+
+./setup.sh -Dsabina.backend=jetty -Dsabina.benchmark.repository=mysql

+ 6 - 1
frameworks/Java/sabina/pom.xml

@@ -36,7 +36,7 @@
 
 
         <db.host>localhost</db.host>
         <db.host>localhost</db.host>
 
 
-        <sabina-version>1.1.1</sabina-version>
+        <sabina-version>1.3.0</sabina-version>
     </properties>
     </properties>
 
 
     <repositories>
     <repositories>
@@ -92,6 +92,11 @@
             <artifactId>mysql-connector-java</artifactId>
             <artifactId>mysql-connector-java</artifactId>
             <version>5.1.28</version>
             <version>5.1.28</version>
         </dependency>
         </dependency>
+        <dependency>
+            <groupId>org.mongodb</groupId>
+            <artifactId>mongo-java-driver</artifactId>
+            <version>3.0.0</version>
+        </dependency>
 
 
         <dependency>
         <dependency>
             <groupId>org.testng</groupId>
             <groupId>org.testng</groupId>

+ 1 - 1
frameworks/Java/sabina/setup.sh

@@ -4,4 +4,4 @@
 source $IROOT/java8.installed
 source $IROOT/java8.installed
 
 
 mvn clean package -DskipTests -Ddb.host=${DBHOST}
 mvn clean package -DskipTests -Ddb.host=${DBHOST}
-${JAVA_HOME}/bin/java -jar target/sabina-1.0.0.jar &
+${JAVA_HOME}/bin/java $@ -jar target/sabina-1.0.0.jar

+ 59 - 134
frameworks/Java/sabina/src/main/java/sabina/benchmark/Application.java

@@ -20,39 +20,29 @@ import static sabina.Sabina.*;
 import static sabina.content.JsonContent.toJson;
 import static sabina.content.JsonContent.toJson;
 import static sabina.view.MustacheView.renderMustache;
 import static sabina.view.MustacheView.renderMustache;
 
 
-import com.mchange.v2.c3p0.ComboPooledDataSource;
 import sabina.Request;
 import sabina.Request;
+import sabina.server.MatcherFilter;
 
 
-import java.sql.*;
 import java.util.*;
 import java.util.*;
 import java.util.Date;
 import java.util.Date;
-import java.util.concurrent.ThreadLocalRandom;
-
-import javax.sql.DataSource;
+import javax.servlet.FilterConfig;
+import javax.servlet.annotation.WebFilter;
 
 
 /**
 /**
  * .
  * .
  */
  */
-final class Application {
-    private static final String SETTINGS_RESOURCE = "/server.properties";
-    private static final Properties SETTINGS = loadConfiguration ();
-
-    private static final String JDBC_URL = SETTINGS.getProperty ("mysql.uri")
-        .replace ("${db.host}", "localhost"); // TODO Move this to Gradle build
-    private static final DataSource DATA_SOURCE = createSessionFactory ();
-    private static final int DB_ROWS = 10000;
-
-    private static final boolean AUTOCOMMIT = getProperty ("sabina.benchmark.autocommit") != null;
-    private static final String SELECT_WORLD = "select * from world where id = ?";
-    private static final String UPDATE_WORLD = "update world set randomNumber = ? where id = ?";
-    private static final String SELECT_FORTUNES = "select * from fortune";
+@WebFilter ("/*")
+final class Application extends MatcherFilter {
+    static final String SETTINGS_RESOURCE = "/server.properties";
+    static final Repository REPOSITORY = loadRepository ();
+    static final int DB_ROWS = 10000;
 
 
     private static final String MESSAGE = "Hello, World!";
     private static final String MESSAGE = "Hello, World!";
     private static final String CONTENT_TYPE_TEXT = "text/plain";
     private static final String CONTENT_TYPE_TEXT = "text/plain";
     private static final String CONTENT_TYPE_JSON = "application/json";
     private static final String CONTENT_TYPE_JSON = "application/json";
     private static final String QUERIES_PARAM = "queries";
     private static final String QUERIES_PARAM = "queries";
 
 
-    private static Properties loadConfiguration () {
+    static Properties loadConfiguration () {
         try {
         try {
             Properties settings = new Properties ();
             Properties settings = new Properties ();
             settings.load (Class.class.getResourceAsStream (SETTINGS_RESOURCE));
             settings.load (Class.class.getResourceAsStream (SETTINGS_RESOURCE));
@@ -63,21 +53,43 @@ final class Application {
         }
         }
     }
     }
 
 
-    private static DataSource createSessionFactory () {
+    static Repository loadRepository () {
+        switch (getProperty ("sabina.benchmark.repository", "mysql")) {
+            case "mongodb":
+                return new MongoDbRepository (loadConfiguration ());
+            case "mysql":
+            default:
+                return new MySqlRepository (loadConfiguration ());
+        }
+    }
+
+    private static Object getDb (Request it) {
         try {
         try {
-            ComboPooledDataSource dataSource = new ComboPooledDataSource ();
-            dataSource.setMinPoolSize (32);
-            dataSource.setMaxPoolSize (256);
-            dataSource.setCheckoutTimeout (1800);
-            dataSource.setMaxStatements (50);
-            dataSource.setJdbcUrl (JDBC_URL);
-            return dataSource;
+            final World[] worlds = REPOSITORY.getWorlds (getQueries (it), false);
+            it.response.type (CONTENT_TYPE_JSON);
+            return toJson (it.queryParams (QUERIES_PARAM) == null? worlds[0] : worlds);
         }
         }
-        catch (Exception ex) {
-            throw new RuntimeException (ex);
+        catch (Exception e){
+            e.printStackTrace ();
+            throw e;
         }
         }
     }
     }
 
 
+    private static Object getFortunes (Request it) {
+        List<Fortune> fortunes = REPOSITORY.getFortunes ();
+        fortunes.add (new Fortune (0, "Additional fortune added at request time."));
+        fortunes.sort ((a, b) -> a.message.compareTo (b.message));
+
+        it.response.type ("text/html; charset=utf-8");
+        return renderMustache ("/fortunes.mustache", fortunes);
+    }
+
+    private static Object getUpdates (Request it) {
+        World[] worlds = REPOSITORY.getWorlds (getQueries (it), true);
+        it.response.type (CONTENT_TYPE_JSON);
+        return toJson (it.queryParams (QUERIES_PARAM) == null? worlds[0] : worlds);
+    }
+
     private static int getQueries (final Request request) {
     private static int getQueries (final Request request) {
         try {
         try {
             String parameter = request.queryParams (QUERIES_PARAM);
             String parameter = request.queryParams (QUERIES_PARAM);
@@ -97,118 +109,22 @@ final class Application {
         }
         }
     }
     }
 
 
-    private static Object getJson (Request it) {
-        it.response.type (CONTENT_TYPE_JSON);
-        return toJson (new Message ());
-    }
-
-    private static Object getDb (Request it) {
-        final int queries = getQueries (it);
-        final World[] worlds = new World[queries];
-
-        try (final Connection con = DATA_SOURCE.getConnection ()) {
-            final Random random = ThreadLocalRandom.current ();
-            final PreparedStatement stmt = con.prepareStatement (SELECT_WORLD);
-
-            for (int ii = 0; ii < queries; ii++) {
-                stmt.setInt (1, random.nextInt (DB_ROWS) + 1);
-                final ResultSet rs = stmt.executeQuery ();
-                while (rs.next ())
-                    worlds[ii] = new World (rs.getInt (1), rs.getInt (2));
-            }
-        }
-        catch (SQLException e) {
-            e.printStackTrace ();
-        }
-
-        it.response.type (CONTENT_TYPE_JSON);
-        return toJson (it.queryParams (QUERIES_PARAM) == null? worlds[0] : worlds);
-    }
-
-    private static Object getFortunes (Request it) {
-        final List<Fortune> fortunes = new ArrayList<> ();
-
-        try (final Connection con = DATA_SOURCE.getConnection ()) {
-            final ResultSet rs = con.prepareStatement (SELECT_FORTUNES).executeQuery ();
-            while (rs.next ())
-                fortunes.add (new Fortune (rs.getInt (1), rs.getString (2)));
-        }
-        catch (SQLException e) {
-            e.printStackTrace ();
-        }
-
-        fortunes.add (new Fortune (0, "Additional fortune added at request time."));
-        fortunes.sort ((a, b) -> a.message.compareTo (b.message));
-
-        it.response.type ("text/html; charset=utf-8");
-        return renderMustache ("/fortunes.mustache", fortunes);
-    }
-
-    private static Object getUpdates (Request it) {
-        final int queries = getQueries (it);
-        final World[] worlds = new World[queries];
-
-        try (final Connection con = DATA_SOURCE.getConnection ()) {
-            con.setAutoCommit (AUTOCOMMIT);
-
-            final Random random = ThreadLocalRandom.current ();
-            final PreparedStatement stmtSelect = con.prepareStatement (SELECT_WORLD);
-            final PreparedStatement stmtUpdate = con.prepareStatement (UPDATE_WORLD);
-
-            for (int ii = 0; ii < queries; ii++) {
-                stmtSelect.setInt (1, random.nextInt (DB_ROWS) + 1);
-                final ResultSet rs = stmtSelect.executeQuery ();
-                while (rs.next ()) {
-                    worlds[ii] = new World (rs.getInt (1), rs.getInt (2));
-                    stmtUpdate.setInt (1, random.nextInt (DB_ROWS) + 1);
-                    stmtUpdate.setInt (2, worlds[ii].id);
-
-                    if (AUTOCOMMIT) {
-                        stmtUpdate.executeUpdate ();
-                    }
-                    else {
-                        stmtUpdate.addBatch ();
-                    }
-                }
-            }
-
-            if (!AUTOCOMMIT) {
-                int count = 0;
-                boolean retrying;
-
-                do {
-                    try {
-                        stmtUpdate.executeBatch ();
-                        retrying = false;
-                    }
-                    catch (BatchUpdateException e) {
-                        retrying = true;
-                    }
-                }
-                while (count++ < 10 && retrying);
-
-                con.commit ();
-            }
-        }
-        catch (SQLException e) {
-            e.printStackTrace ();
-        }
-
-        it.response.type (CONTENT_TYPE_JSON);
-        return toJson (it.queryParams (QUERIES_PARAM) == null? worlds[0] : worlds);
-    }
-
     private static Object getPlaintext (Request it) {
     private static Object getPlaintext (Request it) {
         it.response.type (CONTENT_TYPE_TEXT);
         it.response.type (CONTENT_TYPE_TEXT);
         return MESSAGE;
         return MESSAGE;
     }
     }
 
 
+    private static Object getJson (Request it) {
+        it.response.type (CONTENT_TYPE_JSON);
+        return toJson (new Message ());
+    }
+
     private static void addCommonHeaders (Request it) {
     private static void addCommonHeaders (Request it) {
         it.header ("Server", "Undertow/1.1.2");
         it.header ("Server", "Undertow/1.1.2");
-        it.response.raw ().addDateHeader ("Date", new Date ().getTime ());
+        it.response.addDateHeader ("Date", new Date ().getTime ());
     }
     }
 
 
-    public static void main (String[] args) {
+    private static void routes () {
         get ("/json", Application::getJson);
         get ("/json", Application::getJson);
         get ("/db", Application::getDb);
         get ("/db", Application::getDb);
         get ("/query", Application::getDb);
         get ("/query", Application::getDb);
@@ -216,9 +132,18 @@ final class Application {
         get ("/update", Application::getUpdates);
         get ("/update", Application::getUpdates);
         get ("/plaintext", Application::getPlaintext);
         get ("/plaintext", Application::getPlaintext);
         after (Application::addCommonHeaders);
         after (Application::addCommonHeaders);
+    }
 
 
-        host (SETTINGS.getProperty ("web.host"));
-        port (SETTINGS.getProperty ("web.port"));
+    public static void main (String[] args) {
+        routes ();
+
+        Properties settings = loadConfiguration ();
+        host (settings.getProperty ("web.host"));
+        port (settings.getProperty ("web.port"));
         start ();
         start ();
     }
     }
+
+    @Override protected void routes (FilterConfig filterConfig) {
+        routes ();
+    }
 }
 }

+ 0 - 5
frameworks/Java/sabina/src/main/java/sabina/benchmark/Fortune.java

@@ -14,11 +14,6 @@
 
 
 package sabina.benchmark;
 package sabina.benchmark;
 
 
-/**
- * TODO .
- *
- * @author jam
- */
 final class Fortune {
 final class Fortune {
     final int id;
     final int id;
     final String message;
     final String message;

+ 91 - 0
frameworks/Java/sabina/src/main/java/sabina/benchmark/MongoDbRepository.java

@@ -0,0 +1,91 @@
+/*
+ * Copyright © 2015 Juan José Aguililla. All rights reserved.
+ *
+ * Licensed 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.
+ */
+
+package sabina.benchmark;
+
+import static com.mongodb.client.model.Filters.eq;
+import static java.lang.Integer.parseInt;
+import static sabina.benchmark.Application.DB_ROWS;
+
+import java.util.*;
+import java.util.concurrent.ThreadLocalRandom;
+
+import com.mongodb.*;
+import com.mongodb.client.MongoCollection;
+import com.mongodb.client.MongoDatabase;
+import org.bson.Document;
+
+final class MongoDbRepository implements Repository {
+    private MongoCollection<Document> worldCollection;
+    private MongoCollection<Document> fortuneCollection;
+
+    MongoDbRepository (Properties settings) {
+        final int PORT = parseInt (settings.getProperty ("mongodb.port"));
+        final String HOST = settings.getProperty ("mongodb.host");
+        final String DATABASE = settings.getProperty ("mongodb.database");
+        final String WORLD = settings.getProperty ("mongodb.world.collection");
+        final String FORTUNE = settings.getProperty ("mongodb.fortune.collection");
+
+        MongoClient mongoClient = new MongoClient (HOST, PORT);
+        MongoDatabase db = mongoClient.getDatabase (DATABASE);
+        worldCollection = db.getCollection (WORLD);
+        fortuneCollection = db.getCollection (FORTUNE);
+    }
+
+    @Override public List<Fortune> getFortunes () {
+        List<Fortune> fortunes = new ArrayList<> ();
+
+        fortuneCollection.find ().forEach ((Block<Document>)doc ->
+            fortunes.add (new Fortune (doc.get ("_id", Double.class).intValue (), (String)doc.get
+                ("message")))
+        );
+
+        return fortunes;
+    }
+
+    @Override public World[] getWorlds (int queries, boolean update) {
+        final World[] worlds = new World[queries];
+        final Random random = ThreadLocalRandom.current ();
+
+        for (int ii = 0; ii < queries; ii++) {
+            int id = random.nextInt (DB_ROWS) + 1;
+            worlds[ii] = update? updateWorld (id, random.nextInt (DB_ROWS) + 1) : findWorld (id);
+        }
+
+        return worlds;
+    }
+
+    private World findWorld (int id) {
+        return createWorld (worldCollection.find(eq ("_id", (double)id)).first ());
+    }
+
+    private World createWorld (Document world) {
+        try {
+            return new World (world.get ("_id", Double.class).intValue (), world.get
+                ("randomNumber", Double.class).intValue ());
+        }
+        catch (ClassCastException e) {
+            return new World (world.get ("_id", Double.class).intValue (), world.get
+                ("randomNumber", Integer.class));
+        }
+    }
+
+    public World updateWorld (int id, int random) {
+        Document newWorld = new Document ("_id", (double)id).append ("randomNumber", (double)
+            random);
+        worldCollection.replaceOne (eq ("_id", (double)id), newWorld);
+
+        return new World (id, random);
+    }
+}

+ 139 - 0
frameworks/Java/sabina/src/main/java/sabina/benchmark/MySqlRepository.java

@@ -0,0 +1,139 @@
+/*
+ * Copyright © 2015 Juan José Aguililla. All rights reserved.
+ *
+ * Licensed 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.
+ */
+
+package sabina.benchmark;
+
+import static java.lang.System.getProperty;
+import static sabina.benchmark.Application.DB_ROWS;
+
+import java.sql.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+import java.util.Random;
+import java.util.concurrent.ThreadLocalRandom;
+
+import javax.sql.DataSource;
+
+import com.mchange.v2.c3p0.ComboPooledDataSource;
+
+final class MySqlRepository implements Repository {
+    private static final boolean AUTOCOMMIT = getProperty ("sabina.benchmark.autocommit") != null;
+    private static final String SELECT_WORLD = "select * from world where id = ?";
+    private static final String UPDATE_WORLD = "update world set randomNumber = ? where id = ?";
+    private static final String SELECT_FORTUNES = "select * from fortune";
+
+    private final DataSource DATA_SOURCE;
+
+    MySqlRepository (Properties settings) {
+        final String jdbcUrl = settings.getProperty ("mysql.uri");
+        DATA_SOURCE = createSessionFactory (jdbcUrl);
+    }
+
+    private DataSource createSessionFactory (String jdbcUrl) {
+        try {
+            ComboPooledDataSource dataSource = new ComboPooledDataSource ();
+            dataSource.setMinPoolSize (32);
+            dataSource.setMaxPoolSize (256);
+            dataSource.setCheckoutTimeout (1800);
+            dataSource.setMaxStatements (50);
+            dataSource.setJdbcUrl (jdbcUrl);
+            return dataSource;
+        }
+        catch (Exception ex) {
+            throw new RuntimeException (ex);
+        }
+    }
+
+    private void commitUpdate (Connection con, PreparedStatement stmtUpdate)
+        throws SQLException {
+        int count = 0;
+        boolean retrying;
+
+        do {
+            try {
+                stmtUpdate.executeBatch ();
+                retrying = false;
+            }
+            catch (BatchUpdateException e) {
+                retrying = true;
+            }
+        }
+        while (count++ < 10 && retrying);
+
+        con.commit ();
+    }
+
+    private void updateWorld (World world, PreparedStatement stmtUpdate)
+        throws SQLException {
+        stmtUpdate.setInt (1, world.randomNumber);
+        stmtUpdate.setInt (2, world.id);
+
+        if (AUTOCOMMIT) {
+            stmtUpdate.executeUpdate ();
+        }
+        else {
+            stmtUpdate.addBatch ();
+        }
+    }
+
+    @Override public List<Fortune> getFortunes () {
+        final List<Fortune> fortunes = new ArrayList<> ();
+
+        try (final Connection con = DATA_SOURCE.getConnection ()) {
+            final ResultSet rs = con.prepareStatement (SELECT_FORTUNES).executeQuery ();
+            while (rs.next ())
+                fortunes.add (new Fortune (rs.getInt (1), rs.getString (2)));
+        }
+        catch (SQLException e) {
+            e.printStackTrace ();
+        }
+
+        return fortunes;
+    }
+
+    @Override public World[] getWorlds (int queries, boolean update) {
+        final World[] worlds = new World[queries];
+
+        try (final Connection con = DATA_SOURCE.getConnection ()) {
+            if (update)
+                con.setAutoCommit (AUTOCOMMIT);
+
+            final Random random = ThreadLocalRandom.current ();
+            final PreparedStatement stmtSelect = con.prepareStatement (SELECT_WORLD);
+            final PreparedStatement stmtUpdate = update? con.prepareStatement (UPDATE_WORLD) : null;
+
+            for (int ii = 0; ii < queries; ii++) {
+                stmtSelect.setInt (1, random.nextInt (DB_ROWS) + 1);
+                final ResultSet rs = stmtSelect.executeQuery ();
+                while (rs.next ()) {
+                    worlds[ii] = new World (rs.getInt (1), rs.getInt (2));
+
+                    if (update) {
+                        worlds[ii] = new World (worlds[ii].id, random.nextInt (DB_ROWS) + 1);
+                        updateWorld (worlds[ii], stmtUpdate);
+                    }
+                }
+            }
+
+            if (update && !AUTOCOMMIT)
+                commitUpdate (con, stmtUpdate);
+        }
+        catch (SQLException e) {
+            e.printStackTrace ();
+        }
+
+        return worlds;
+    }
+}

+ 22 - 0
frameworks/Java/sabina/src/main/java/sabina/benchmark/Repository.java

@@ -0,0 +1,22 @@
+/*
+ * Copyright © 2015 Juan José Aguililla. All rights reserved.
+ *
+ * Licensed 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.
+ */
+
+package sabina.benchmark;
+
+import java.util.List;
+
+interface Repository {
+    List<Fortune> getFortunes ();
+    World[] getWorlds (int queries, boolean update);
+}

+ 5 - 2
frameworks/Java/sabina/src/main/resources/server.properties

@@ -15,8 +15,11 @@
 web.port = 5050
 web.port = 5050
 web.host = 0.0.0.0
 web.host = 0.0.0.0
 
 
-mongodb.uri = ${db.host}:27017
-mongodb.name = hello_world
+mongodb.host = ${db.host}
+mongodb.port = 27017
+mongodb.database = hello_world
+mongodb.world.collection = world
+mongodb.fortune.collection = fortune
 
 
 mysql.uri = jdbc:mysql://${db.host}:3306/hello_world?\
 mysql.uri = jdbc:mysql://${db.host}:3306/hello_world?\
 user=benchmarkdbuser&\
 user=benchmarkdbuser&\

+ 13 - 28
frameworks/Java/sabina/src/test/java/sabina/benchmark/ApplicationTest.java

@@ -16,7 +16,6 @@ package sabina.benchmark;
 
 
 import static org.apache.http.client.fluent.Request.Get;
 import static org.apache.http.client.fluent.Request.Get;
 import static org.testng.AssertJUnit.*;
 import static org.testng.AssertJUnit.*;
-import static sabina.benchmark.Application.main;
 import static sabina.Sabina.stop;
 import static sabina.Sabina.stop;
 
 
 import java.io.IOException;
 import java.io.IOException;
@@ -39,37 +38,13 @@ import org.testng.annotations.Test;
  * <p>TODO Change assert's order
  * <p>TODO Change assert's order
  */
  */
 public final class ApplicationTest {
 public final class ApplicationTest {
-    private static final int THREADS = 16, EXECUTIONS = 32, WARM_UP = 32;
+    private static final int THREADS = 1, EXECUTIONS = 1;
 
 
     private static final String ENDPOINT = "http://localhost:5050";
     private static final String ENDPOINT = "http://localhost:5050";
     private static final Gson GSON = new Gson ();
     private static final Gson GSON = new Gson ();
 
 
     @BeforeClass public static void setup () {
     @BeforeClass public static void setup () {
-        main (null);
-    }
-
-    @BeforeClass public void warm_up () throws IOException {
-        for (int ii = 0; ii < WARM_UP; ii++) {
-            json ();
-            plaintext ();
-            no_query_parameter ();
-            empty_query_parameter ();
-            text_query_parameter ();
-            zero_queries ();
-            one_thousand_queries ();
-            one_query ();
-            ten_queries ();
-            five_hundred_queries ();
-            fortunes ();
-            no_updates_parameter ();
-            empty_updates_parameter ();
-            text_updates_parameter ();
-            zero_updates ();
-            one_thousand_updates ();
-            one_update ();
-            ten_updates ();
-            five_hundred_updates ();
-        }
+        Application.main (null);
     }
     }
 
 
     @AfterClass public static void close () {
     @AfterClass public static void close () {
@@ -134,6 +109,11 @@ public final class ApplicationTest {
         checkDbRequest ("/query?queries=10", 10);
         checkDbRequest ("/query?queries=10", 10);
     }
     }
 
 
+    @Test(threadPoolSize = THREADS, invocationCount = EXECUTIONS)
+    public void one_hundred_queries () throws IOException {
+        checkDbRequest ("/query?queries=100", 100);
+    }
+
     @Test(threadPoolSize = THREADS, invocationCount = EXECUTIONS)
     @Test(threadPoolSize = THREADS, invocationCount = EXECUTIONS)
     public void five_hundred_queries () throws IOException {
     public void five_hundred_queries () throws IOException {
         checkDbRequest ("/query?queries=500", 500);
         checkDbRequest ("/query?queries=500", 500);
@@ -192,6 +172,11 @@ public final class ApplicationTest {
         checkDbRequest ("/update?queries=10", 10);
         checkDbRequest ("/update?queries=10", 10);
     }
     }
 
 
+    @Test(threadPoolSize = THREADS, invocationCount = EXECUTIONS)
+    public void one_hundred_updates () throws IOException {
+        checkDbRequest ("/update?queries=100", 100);
+    }
+
     @Test(threadPoolSize = THREADS, invocationCount = EXECUTIONS)
     @Test(threadPoolSize = THREADS, invocationCount = EXECUTIONS)
     public void five_hundred_updates () throws IOException {
     public void five_hundred_updates () throws IOException {
         checkDbRequest ("/update?queries=500", 500);
         checkDbRequest ("/update?queries=500", 500);
@@ -218,7 +203,7 @@ public final class ApplicationTest {
         assertTrue (res.getFirstHeader ("Server") != null);
         assertTrue (res.getFirstHeader ("Server") != null);
         assertTrue (res.getFirstHeader ("Date") != null);
         assertTrue (res.getFirstHeader ("Date") != null);
         assertEquals (content.length (), res.getEntity ().getContentLength ());
         assertEquals (content.length (), res.getEntity ().getContentLength ());
-        assertEquals (contentType, res.getEntity ().getContentType ().getValue ());
+        assertTrue (res.getEntity ().getContentType ().getValue ().contains (contentType));
     }
     }
 
 
     private void checkResultItems (String result, int size) {
     private void checkResultItems (String result, int size) {

+ 3 - 0
frameworks/Java/sabina/undertow-mongodb.sh

@@ -0,0 +1,3 @@
+#!/bin/bash
+
+./setup.sh -Dsabina.backend=undertow -Dsabina.benchmark.repository=mongodb

+ 3 - 0
frameworks/Java/sabina/undertow.sh

@@ -0,0 +1,3 @@
+#!/bin/bash
+
+./setup.sh -Dsabina.backend=undertow -Dsabina.benchmark.repository=mysql

+ 1 - 1
frameworks/Java/undertow/install.sh

@@ -1,3 +1,3 @@
 #!/bin/bash
 #!/bin/bash
 
 
-fw_depends java7 maven
+fw_depends java8 maven

+ 10 - 10
frameworks/Java/undertow/pom.xml

@@ -15,17 +15,17 @@
         <dependency>
         <dependency>
             <groupId>io.undertow</groupId>
             <groupId>io.undertow</groupId>
             <artifactId>undertow-core</artifactId>
             <artifactId>undertow-core</artifactId>
-            <version>1.0.14.Final</version>
+            <version>1.2.5.Final</version>
         </dependency>
         </dependency>
         <dependency>
         <dependency>
             <groupId>org.jboss.xnio</groupId>
             <groupId>org.jboss.xnio</groupId>
             <artifactId>xnio-api</artifactId>
             <artifactId>xnio-api</artifactId>
-            <version>3.2.2.Final</version>
+            <version>3.3.1.Final</version>
         </dependency>
         </dependency>
         <dependency>
         <dependency>
             <groupId>org.jboss.xnio</groupId>
             <groupId>org.jboss.xnio</groupId>
             <artifactId>xnio-nio</artifactId>
             <artifactId>xnio-nio</artifactId>
-            <version>3.2.2.Final</version>
+            <version>3.3.1.Final</version>
         </dependency>
         </dependency>
         <!-- Database drivers -->
         <!-- Database drivers -->
         <dependency>
         <dependency>
@@ -53,29 +53,29 @@
         <dependency>
         <dependency>
             <groupId>com.google.guava</groupId>
             <groupId>com.google.guava</groupId>
             <artifactId>guava</artifactId>
             <artifactId>guava</artifactId>
-            <version>16.0.1</version>
+            <version>18.0</version>
         </dependency>
         </dependency>
         <!-- JSON encoding -->
         <!-- JSON encoding -->
         <dependency>
         <dependency>
             <groupId>com.fasterxml.jackson.core</groupId>
             <groupId>com.fasterxml.jackson.core</groupId>
             <artifactId>jackson-databind</artifactId>
             <artifactId>jackson-databind</artifactId>
-            <version>2.3.3</version>
+            <version>2.5.3</version>
         </dependency>
         </dependency>
         <dependency>
         <dependency>
             <groupId>com.fasterxml.jackson.core</groupId>
             <groupId>com.fasterxml.jackson.core</groupId>
             <artifactId>jackson-annotations</artifactId>
             <artifactId>jackson-annotations</artifactId>
-            <version>2.3.3</version>
+            <version>2.5.3</version>
         </dependency>
         </dependency>
         <dependency>
         <dependency>
             <groupId>com.fasterxml.jackson.core</groupId>
             <groupId>com.fasterxml.jackson.core</groupId>
             <artifactId>jackson-core</artifactId>
             <artifactId>jackson-core</artifactId>
-            <version>2.3.3</version>
+            <version>2.5.3</version>
         </dependency>
         </dependency>
         <!-- HTML templates -->
         <!-- HTML templates -->
         <dependency>
         <dependency>
             <groupId>com.github.spullara.mustache.java</groupId>
             <groupId>com.github.spullara.mustache.java</groupId>
             <artifactId>compiler</artifactId>
             <artifactId>compiler</artifactId>
-            <version>0.8.13</version>
+            <version>0.9.0</version>
         </dependency>
         </dependency>
     </dependencies>
     </dependencies>
 
 
@@ -87,8 +87,8 @@
                 <artifactId>maven-compiler-plugin</artifactId>
                 <artifactId>maven-compiler-plugin</artifactId>
                 <version>3.1</version>
                 <version>3.1</version>
                 <configuration>
                 <configuration>
-                    <source>1.7</source>
-                    <target>1.7</target>
+                    <source>1.8</source>
+                    <target>1.8</target>
                     <optimize>true</optimize>
                     <optimize>true</optimize>
                     <debug>false</debug>
                     <debug>false</debug>
                 </configuration>
                 </configuration>

+ 2 - 2
frameworks/Java/undertow/setup.sh

@@ -1,9 +1,9 @@
 #!/bin/bash
 #!/bin/bash
 # load java environment variables
 # load java environment variables
-source $IROOT/java7.installed
+source $IROOT/java8.installed
 
 
 sed -i 's|DATABASE_HOST|'"${DBHOST}"'|g' src/main/resources/hello/server.properties
 sed -i 's|DATABASE_HOST|'"${DBHOST}"'|g' src/main/resources/hello/server.properties
 
 
 mvn clean compile assembly:single
 mvn clean compile assembly:single
 cd target
 cd target
-java -jar undertow-example-0.1-jar-with-dependencies.jar &
+$JAVA_HOME/bin/java -jar undertow-example-0.1-jar-with-dependencies.jar &

+ 2 - 0
frameworks/Java/undertow/src/main/java/hello/HelloWebServer.java

@@ -123,6 +123,8 @@ public final class HelloWebServer {
         .setSocketOption(Options.BACKLOG, 10000)
         .setSocketOption(Options.BACKLOG, 10000)
         .setServerOption(UndertowOptions.ALWAYS_SET_KEEP_ALIVE, false) //don't send a keep-alive header for HTTP/1.1 requests, as it is not required
         .setServerOption(UndertowOptions.ALWAYS_SET_KEEP_ALIVE, false) //don't send a keep-alive header for HTTP/1.1 requests, as it is not required
         .setServerOption(UndertowOptions.ALWAYS_SET_DATE, true)
         .setServerOption(UndertowOptions.ALWAYS_SET_DATE, true)
+        .setServerOption(UndertowOptions.ENABLE_CONNECTOR_STATISTICS, false)
+        .setServerOption(UndertowOptions.RECORD_REQUEST_START_TIME, false)
         .setHandler(Handlers.header(Handlers.path()
         .setHandler(Handlers.header(Handlers.path()
             .addPrefixPath("/json",
             .addPrefixPath("/json",
                 new JsonHandler(objectMapper))
                 new JsonHandler(objectMapper))

+ 43 - 6
frameworks/Java/vertx/README.md

@@ -1,22 +1,43 @@
-# Vertx Benchmarking Test
+# Vertx 2.x Benchmarking Test
 
 
-This is the vertx portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+This is the vertx 2.x portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+
+### Plaintext Test
+
+* [Plaintext test source](WebServer.java)
+
+### JSON Serialization Test
 
 
-### JSON Encoding Test
 * [JSON test source](WebServer.java)
 * [JSON test source](WebServer.java)
 
 
-### Data-Store/Database Mapping Test
+### Database Single query Test
+
+* [Database Single query test source](WebServer.java)
+
+### Database Multiple queries Test
+
+* [Database Multiple queries test source](WebServer.java)
+
+### Database Data updates Test
+
+* [Database Data updates test source](WebServer.java)
+
+### Fortunes Test
 
 
-* [Database test source](WebServer.java)
+* [Fortunes test source](WebServer.java)
 
 
 ## Versions
 ## Versions
 
 
-* [Java OpenJDK 1.7.0_09](http://openjdk.java.net/)
+* [Java OpenJDK 1.7.0_79](http://openjdk.java.net/)
 * [vertx 2.1.5](http://vertx.io/)
 * [vertx 2.1.5](http://vertx.io/)
 
 
 
 
 ## Test URLs
 ## Test URLs
 
 
+### Plaintext Test
+
+    http://localhost:8080/plaintext
+
 ### JSON Encoding Test
 ### JSON Encoding Test
 
 
     http://localhost:8080/json
     http://localhost:8080/json
@@ -24,3 +45,19 @@ This is the vertx portion of a [benchmarking test suite](../) comparing a variet
 ### Database Mapping Test
 ### Database Mapping Test
 
 
     http://localhost:8080/db?queries=5
     http://localhost:8080/db?queries=5
+
+### Database Single query Test
+
+    http://localhost:8080/db
+
+### Database Multiple queries Test
+
+    http://localhost:8080/queries?queries=5
+
+### Database Data updates Test
+
+    http://localhost:8080/updates?queries=3
+
+### Fortunes Test
+
+    http://localhost:8080/fortunes

+ 139 - 38
frameworks/Java/vertx/WebServer.java

@@ -15,38 +15,67 @@ import java.util.Date;
 import java.util.Random;
 import java.util.Random;
 import java.util.concurrent.ThreadLocalRandom;
 import java.util.concurrent.ThreadLocalRandom;
 
 
+import freemarker.template.Template;
+import freemarker.template.Configuration;
+import java.io.StringReader;
+import java.io.Writer;
+import java.io.StringWriter;
+import java.util.List;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.ArrayList;
+
 public class WebServer extends Verticle implements Handler<HttpServerRequest> {
 public class WebServer extends Verticle implements Handler<HttpServerRequest> {
 
 
   private final Buffer helloWorldBuffer = new Buffer("Hello, World!");
   private final Buffer helloWorldBuffer = new Buffer("Hello, World!");
   private final String helloWorldContentLength = String.valueOf(helloWorldBuffer.length());
   private final String helloWorldContentLength = String.valueOf(helloWorldBuffer.length());
   private final DateFormat DATE_FORMAT = new SimpleDateFormat("EEE, dd MMM yyyyy HH:mm:ss z");
   private final DateFormat DATE_FORMAT = new SimpleDateFormat("EEE, dd MMM yyyyy HH:mm:ss z");
+  private final Random random = ThreadLocalRandom.current();
   private String dateString;
   private String dateString;
 
 
-  private final String PATH_PLAINTEXT = "/plaintext";
-  private final String PATH_JSON = "/json";
-  private final String PATH_DB = "/db";
-  private final String PATH_QUERIES = "/queries";
-  private final String RESPONSE_TYPE_PLAIN = "text/plain";
-  private final String RESPONSE_TYPE_JSON = "application/json";
-  private final String HEADER_CONTENT_TYPE = "Content-Type";
-  private final String HEADER_CONTENT_LENGTH = "Content-Length";
-  private final String HEADER_SERVER = "Server";
-  private final String HEADER_SERVER_VERTX = "vert.x";
-  private final String HEADER_DATE = "Date";
-  private final String MONGO_ADDRESS = "hello.persistor";
-  private final String UNDERSCORE_ID = "_id";
-  private final String TEXT_ID = "id";
-  private final String TEXT_RESULT = "result";
-  private final String TEXT_QUERIES = "queries";
-  private final String TEXT_MESSAGE = "message";
-  private final String TEXT_ACTION = "action";
-  private final String TEXT_FINDONE = "findone";
-  private final String TEXT_COLLECTION = "collection";
-  private final String TEXT_WORLD = "World";
-  private final String TEXT_MATCHER = "matcher";
+  private static final String PATH_PLAINTEXT = "/plaintext";
+  private static final String PATH_JSON = "/json";
+  private static final String PATH_DB = "/db";
+  private static final String PATH_QUERIES = "/queries";
+  private static final String PATH_UPDATES = "/updates";
+  private static final String PATH_FORTUNES = "/fortunes";
+  private static final String RESPONSE_TYPE_PLAIN = "text/plain";
+  private static final String RESPONSE_TYPE_HTML = "text/html";
+  private static final String RESPONSE_TYPE_JSON = "application/json";
+  private static final String HEADER_CONTENT_TYPE = "Content-Type";
+  private static final String HEADER_CONTENT_LENGTH = "Content-Length";
+  private static final String HEADER_SERVER = "Server";
+  private static final String HEADER_SERVER_VERTX = "vert.x";
+  private static final String HEADER_DATE = "Date";
+  private static final String MONGO_ADDRESS = "hello.persistor";
+  private static final String FREEMARKER_ADDRESS = "vertx.freemarker";
+  private static final String UNDERSCORE_ID = "_id";
+  private static final String TEXT_ID = "id";
+  private static final String RANDOM_NUMBER = "randomNumber";
+  private static final String TEXT_RESULT = "result";
+  private static final String TEXT_RESULTS = "results";
+  private static final String TEXT_QUERIES = "queries";
+  private static final String TEXT_MESSAGE = "message";
+  private static final String TEXT_MESSAGES = "messages";
+  private static final String ADD_FORTUNE_MESSAGE = "Additional fortune added at request time.";
+  private static final String HELLO_WORLD = "Hello, world!";
+  private static final String TEXT_ACTION = "action";
+  private static final String TEXT_CRITERIA = "criteria";
+  private static final String TEXT_UPDATE = "update";
+  private static final String TEXT_OBJ_NEW = "objNew";
+  private static final String TEXT_FINDONE = "findone";
+  private static final String TEXT_FIND = "find";
+  private static final String TEXT_COLLECTION = "collection";
+  private static final String TEXT_WORLD = "World";
+  private static final String TEXT_FORTUNE = "Fortune";
+  private static final String TEXT_MATCHER = "matcher";
+  private static final String TEMPLATE_FORTUNE = "<!DOCTYPE html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr><#list messages as message><tr><td>${message.id?html}</td><td>${message.message?html}</td></tr></#list></table></body></html>";
+  
+  private Template ftlTemplate;
 
 
   @Override
   @Override
   public void start() {
   public void start() {
+    try { ftlTemplate = new Template(TEXT_FORTUNE, new StringReader(TEMPLATE_FORTUNE), new Configuration(Configuration.VERSION_2_3_22)); } catch (Exception ex) { ex.printStackTrace(); }
     vertx.createHttpServer().requestHandler(WebServer.this).listen(8080);
     vertx.createHttpServer().requestHandler(WebServer.this).listen(8080);
     vertx.setPeriodic(1000, new Handler<Long>() {
     vertx.setPeriodic(1000, new Handler<Long>() {
       @Override
       @Override
@@ -70,7 +99,13 @@ public class WebServer extends Verticle implements Handler<HttpServerRequest> {
         handleDbMongo(req);
         handleDbMongo(req);
         break;
         break;
       case PATH_QUERIES:
       case PATH_QUERIES:
-        handleQueriesMongo(req);
+        handleDBMongo(req,false);
+        break;
+      case PATH_UPDATES:
+        handleDBMongo(req,true);
+        break;
+      case PATH_FORTUNES:
+        handleFortunes(req);
         break;
         break;
       default:
       default:
         req.response().setStatusCode(404);
         req.response().setStatusCode(404);
@@ -82,6 +117,40 @@ public class WebServer extends Verticle implements Handler<HttpServerRequest> {
     dateString = DATE_FORMAT.format(new Date());
     dateString = DATE_FORMAT.format(new Date());
   }
   }
 
 
+  private void handleFortunes(HttpServerRequest req) {
+    final HttpServerResponse resp = req.response();
+    
+    vertx.eventBus().send(
+      MONGO_ADDRESS,
+      new JsonObject()
+          .putString(TEXT_ACTION, TEXT_FIND)
+          .putString(TEXT_COLLECTION, TEXT_FORTUNE),
+      new Handler<Message<JsonObject>>() {
+        @Override
+        public void handle(Message<JsonObject> reply) {
+          JsonArray results = reply.body().getArray(TEXT_RESULTS);
+          
+          List<Fortune> fortunes = new ArrayList<>();
+          for (Object fortune: results) {
+            fortunes.add(new Fortune(
+              ((JsonObject)fortune).getNumber(TEXT_ID).intValue(),
+              ((JsonObject)fortune).getString(TEXT_MESSAGE)));
+          }            
+          fortunes.add(new Fortune(0, ADD_FORTUNE_MESSAGE));
+          Collections.sort(fortunes);
+
+          Map model = new HashMap();
+          model.put(TEXT_MESSAGES, fortunes);
+          Writer writer = new StringWriter();
+          try { ftlTemplate.process(model, writer); } catch (Exception ex) { ex.printStackTrace(); }
+
+          Buffer buff = new Buffer(writer.toString());
+          setHeaders(resp, RESPONSE_TYPE_HTML, String.valueOf(buff.length()));
+          resp.end(buff);
+        }  
+    });
+  }
+
   private void handlePlainText(HttpServerRequest req) {
   private void handlePlainText(HttpServerRequest req) {
     HttpServerResponse resp = req.response();
     HttpServerResponse resp = req.response();
     setHeaders(resp, RESPONSE_TYPE_PLAIN, helloWorldContentLength);
     setHeaders(resp, RESPONSE_TYPE_PLAIN, helloWorldContentLength);
@@ -89,14 +158,14 @@ public class WebServer extends Verticle implements Handler<HttpServerRequest> {
   }
   }
 
 
   private void handleJson(HttpServerRequest req) {
   private void handleJson(HttpServerRequest req) {
-    Buffer buff = new Buffer(Json.encode(Collections.singletonMap(TEXT_MESSAGE, "Hello, world!")));
+    Buffer buff = new Buffer(Json.encode(Collections.singletonMap(TEXT_MESSAGE, HELLO_WORLD)));
     HttpServerResponse resp = req.response();
     HttpServerResponse resp = req.response();
     setHeaders(resp, RESPONSE_TYPE_JSON, String.valueOf(buff.length()));
     setHeaders(resp, RESPONSE_TYPE_JSON, String.valueOf(buff.length()));
     resp.end(buff);
     resp.end(buff);
   }
   }
 
 
   private void handleDbMongo(final HttpServerRequest req) {
   private void handleDbMongo(final HttpServerRequest req) {
-    findRandom(ThreadLocalRandom.current(), new Handler<Message<JsonObject>>() {
+    findRandom(new Handler<Message<JsonObject>>() {
       @Override
       @Override
       public void handle(Message<JsonObject> reply) {
       public void handle(Message<JsonObject> reply) {
         JsonObject world = getResultFromReply(reply);
         JsonObject world = getResultFromReply(reply);
@@ -110,15 +179,11 @@ public class WebServer extends Verticle implements Handler<HttpServerRequest> {
     JsonObject body = reply.body();
     JsonObject body = reply.body();
     JsonObject world = body.getObject(TEXT_RESULT);
     JsonObject world = body.getObject(TEXT_RESULT);
     Object id = world.removeField(UNDERSCORE_ID);
     Object id = world.removeField(UNDERSCORE_ID);
-    if (id instanceof Double) {
-		world.putValue(TEXT_ID, Integer.valueOf(((Double)id).intValue()));
-	} else {
-		world.putValue(TEXT_ID, id);
-	}
+    world.putValue(TEXT_ID, Integer.valueOf(((Double)id).intValue()));
     return world;
     return world;
   }
   }
 
 
-  private void handleQueriesMongo(final HttpServerRequest req) {
+  private void handleDBMongo(final HttpServerRequest req, boolean randomUpdates) {
     int queriesParam = 1;
     int queriesParam = 1;
     try {
     try {
       queriesParam = Integer.parseInt(req.params().get(TEXT_QUERIES));
       queriesParam = Integer.parseInt(req.params().get(TEXT_QUERIES));
@@ -130,14 +195,13 @@ public class WebServer extends Verticle implements Handler<HttpServerRequest> {
     } else if (queriesParam > 500) {
     } else if (queriesParam > 500) {
       queriesParam = 500;
       queriesParam = 500;
     }
     }
-    final MongoHandler dbh = new MongoHandler(req, queriesParam);
-    final Random random = ThreadLocalRandom.current();
+    final MongoHandler dbh = new MongoHandler(req, queriesParam, randomUpdates);
     for (int i = 0; i < queriesParam; i++) {
     for (int i = 0; i < queriesParam; i++) {
-      findRandom(random, dbh);
+      findRandom(dbh);
     }
     }
   }
   }
 
 
-  private void findRandom(Random random, Handler<Message<JsonObject>> handler) {
+  private void findRandom(Handler<Message<JsonObject>> handler) {
     vertx.eventBus().send(
     vertx.eventBus().send(
         MONGO_ADDRESS,
         MONGO_ADDRESS,
         new JsonObject()
         new JsonObject()
@@ -147,6 +211,17 @@ public class WebServer extends Verticle implements Handler<HttpServerRequest> {
         handler);
         handler);
   }
   }
 
 
+  private void updateRandom(JsonObject json) {
+    vertx.eventBus().send(
+        MONGO_ADDRESS,
+        new JsonObject()
+            .putString(TEXT_ACTION, TEXT_UPDATE)
+            .putString(TEXT_COLLECTION, TEXT_WORLD)
+            .putObject(TEXT_CRITERIA, new JsonObject().putValue(UNDERSCORE_ID, json.getValue(TEXT_ID)))
+            .putObject(TEXT_OBJ_NEW, json)
+             );
+  }
+
   private void sendResponse(HttpServerRequest req, String result) {
   private void sendResponse(HttpServerRequest req, String result) {
     Buffer buff = new Buffer(result);
     Buffer buff = new Buffer(result);
     HttpServerResponse resp = req.response();
     HttpServerResponse resp = req.response();
@@ -161,20 +236,27 @@ public class WebServer extends Verticle implements Handler<HttpServerRequest> {
     resp.putHeader(HEADER_DATE, dateString);
     resp.putHeader(HEADER_DATE, dateString);
   }
   }
 
 
-  private class MongoHandler implements Handler<Message<JsonObject>> {
+  private final class MongoHandler implements Handler<Message<JsonObject>> {
     private final HttpServerRequest req;
     private final HttpServerRequest req;
     private final int queries;
     private final int queries;
     private final JsonArray worlds;
     private final JsonArray worlds;
+    private final Random random;
+    private final boolean randomUpdates;
 
 
-    public MongoHandler(HttpServerRequest request, int queriesParam) {
+    public MongoHandler(HttpServerRequest request, int queriesParam, boolean performRandomUpdates) {
       req = request;
       req = request;
       queries = queriesParam;
       queries = queriesParam;
+      randomUpdates = performRandomUpdates;
+      random = ThreadLocalRandom.current();
       worlds = new JsonArray();
       worlds = new JsonArray();
     }
     }
-
     @Override
     @Override
     public void handle(Message<JsonObject> reply) {
     public void handle(Message<JsonObject> reply) {
       JsonObject world = getResultFromReply(reply);
       JsonObject world = getResultFromReply(reply);
+      if (randomUpdates) {
+        world.putValue(RANDOM_NUMBER, (random.nextInt(10000) + 1));
+        updateRandom(world);        
+      }
       worlds.add(world);
       worlds.add(world);
       if (worlds.size() == this.queries) {
       if (worlds.size() == this.queries) {
         // All queries have completed; send the response.
         // All queries have completed; send the response.
@@ -183,6 +265,25 @@ public class WebServer extends Verticle implements Handler<HttpServerRequest> {
       }
       }
     }
     }
   }
   }
+  
+  public final class Fortune implements Comparable<Fortune> {
+    public int id;
+    public String message;
 
 
+    public int getId() {
+      return id;
+    }
+    public String getMessage() {
+      return message;
+    }
+    public Fortune(int id, String message) {
+      this.id = id;
+      this.message = message;
+    }
+    @Override
+    public int compareTo(Fortune other) {
+      return message.compareTo(other.message);
+    }
+  }  
 }
 }
 
 

+ 1 - 1
frameworks/Java/vertx/app.js

@@ -4,7 +4,7 @@ var persistorConf = {
   address: 'hello.persistor',
   address: 'hello.persistor',
   db_name: 'hello_world',
   db_name: 'hello_world',
   host: '127.0.0.1',
   host: '127.0.0.1',
-  pool_size: 20
+  pool_size: 100
 }
 }
 
 
 container.deployModule('io.vertx~mod-mongo-persistor~2.1.1', persistorConf, function (err, dep_id) {
 container.deployModule('io.vertx~mod-mongo-persistor~2.1.1', persistorConf, function (err, dep_id) {

+ 2 - 0
frameworks/Java/vertx/benchmark_config.json

@@ -7,6 +7,8 @@
       "db_url": "/db",
       "db_url": "/db",
       "plaintext_url": "/plaintext",
       "plaintext_url": "/plaintext",
       "query_url": "/queries?queries=",
       "query_url": "/queries?queries=",
+      "update_url": "/updates?queries=",
+      "fortune_url": "/fortunes",
       "port": 8080,
       "port": 8080,
       "approach": "Realistic",
       "approach": "Realistic",
       "classification": "Platform",
       "classification": "Platform",

+ 1 - 1
frameworks/Java/vertx/install.sh

@@ -7,5 +7,5 @@ RETCODE=$(fw_exists ${IROOT}/vert.x-2.1.5.installed)
 
 
 fw_get http://dl.bintray.com/vertx/downloads/vert.x-2.1.5.tar.gz?direct=true -O vert.x-2.1.5.tar.gz
 fw_get http://dl.bintray.com/vertx/downloads/vert.x-2.1.5.tar.gz?direct=true -O vert.x-2.1.5.tar.gz
 fw_untar vert.x-2.1.5.tar.gz
 fw_untar vert.x-2.1.5.tar.gz
-
+wget http://central.maven.org/maven2/org/freemarker/freemarker/2.3.22/freemarker-2.3.22.jar -O ${IROOT}/vert.x-2.1.5/lib/freemarker-2.3.22.jar
 touch ${IROOT}/vert.x-2.1.5.installed
 touch ${IROOT}/vert.x-2.1.5.installed

+ 51 - 21
frameworks/Lua/openresty/app.lua

@@ -3,6 +3,12 @@ local mysql = mysql
 local encode = encode
 local encode = encode
 local random = math.random
 local random = math.random
 local min = math.min
 local min = math.min
+local insert = table.insert
+local sort = table.sort
+local template = require'resty.template'
+template.caching(false)
+-- Compile template, disable cache, enable plain text view to skip filesystem loading
+local view = template.compile([[<!DOCTYPE html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr>{% for _,f in ipairs(fortunes) do %}<tr><td>{{ f.id }}</td><td>{{ f.message }}</td></tr>{% end %}</table></body></html>]], nil, true)
 
 
 local mysqlconn = {
 local mysqlconn = {
 	host = "DBHOSTNAME",
 	host = "DBHOSTNAME",
@@ -11,24 +17,48 @@ local mysqlconn = {
 	user = "benchmarkdbuser",
 	user = "benchmarkdbuser",
 	password = "benchmarkdbpass"
 	password = "benchmarkdbpass"
 }
 }
-return function(ngx)
-	local db = mysql:new()
-	assert(db:connect(mysqlconn))
-	local num_queries = tonumber(ngx.var.arg_queries) or 1
-	-- May seem like a stupid branch, but since we know that
-	-- at a benchmark it will always be taken one way,
-	-- it doesn't matter. For me, after a small warmup, the performance
-	-- is identical to a version without the branch
-	-- http://wiki.luajit.org/Numerical-Computing-Performance-Guide
-	if num_queries == 1 then
-		ngx.print(encode(db:query('SELECT * FROM World WHERE id = '..random(1,10000))[1]))
-	else
-		local worlds = {}
-		num_queries = min(500, num_queries)
-		for i=1, num_queries do
-			worlds[#worlds+1] = db:query('SELECT * FROM World WHERE id = '..random(1,10000))[1]
-		end
-		ngx.print( encode(worlds) )
-	end
-	db:set_keepalive(0, 256)
-end
+return {
+    db = function(ngx)
+        local db = mysql:new()
+        assert(db:connect(mysqlconn))
+        ngx.print(encode(db:query('SELECT * FROM World WHERE id = '..random(1,10000))[1]))
+        db:set_keepalive(0, 256)
+    end,
+    queries = function(ngx)
+        local db = mysql:new()
+        assert(db:connect(mysqlconn))
+        local num_queries = tonumber(ngx.var.arg_queries) or 1
+        -- May seem like a stupid branch, but since we know that
+        -- at a benchmark it will always be taken one way,
+        -- it doesn't matter. For me, after a small warmup, the performance
+        -- is identical to a version without the branch
+        -- http://wiki.luajit.org/Numerical-Computing-Performance-Guide
+        if num_queries < 2 then
+            ngx.print(encode({db:query('SELECT * FROM World WHERE id = '..random(1,10000))[1]}))
+        else
+            local worlds = {}
+            num_queries = min(500, num_queries)
+            for i=1, num_queries do
+                worlds[#worlds+1] = db:query('SELECT * FROM World WHERE id = '..random(1,10000))[1]
+            end
+            ngx.print( encode(worlds) )
+        end
+        db:set_keepalive(0, 256)
+    end,
+    fortunes = function(ngx)
+        local db = mysql:new()
+        assert(db:connect(mysqlconn))
+        local fortunes = db:query('SELECT * FROM Fortune')
+        insert(fortunes, {
+            id = 0,
+            message = "Additional fortune added at request time."
+        })
+        sort(fortunes, function(a, b)
+            return a.message < b.message
+        end)
+        local res = view{fortunes=fortunes}
+        ngx.header['Content-Length'] = #res
+        ngx.print(res)
+        db:set_keepalive(0, 256)
+    end
+}

+ 2 - 1
frameworks/Lua/openresty/benchmark_config.json

@@ -5,7 +5,8 @@
       "setup_file": "setup",
       "setup_file": "setup",
       "json_url": "/json",
       "json_url": "/json",
       "db_url": "/db",
       "db_url": "/db",
-      "query_url": "/db?queries=",
+      "query_url": "/queries?queries=",
+      "fortune_url": "/fortunes",
       "plaintext_url": "/plaintext",
       "plaintext_url": "/plaintext",
       "port": 8080,
       "port": 8080,
       "approach": "Realistic",
       "approach": "Realistic",

+ 3 - 1
frameworks/Lua/openresty/install.sh

@@ -1,3 +1,5 @@
 #!/bin/bash
 #!/bin/bash
 
 
-fw_depends lua nginx openresty 
+fw_depends lua openresty
+
+sudo luarocks install --server=http://rocks.moonscript.org lua-resty-template

+ 11 - 2
frameworks/Lua/openresty/nginx.conf

@@ -9,7 +9,7 @@ http {
     resolver 127.0.0.1;
     resolver 127.0.0.1;
     access_log off;
     access_log off;
     lua_package_path 'CWD/?.lua;;';
     lua_package_path 'CWD/?.lua;;';
-    init_by_lua 'jit.opt.start("minstitch=10"); require "resty.core" encode = require("cjson").encode mysql = require("resty.mysql")';
+    init_by_lua 'jit.opt.start("minstitch=10"); require "resty.core" encode = require("cjson").encode mysql = require("resty.mysql") app = require("app")';
     server {
     server {
         listen       8080;
         listen       8080;
         location /plaintext {
         location /plaintext {
@@ -21,8 +21,17 @@ http {
             default_type "application/json";
             default_type "application/json";
             content_by_lua 'ngx.print(encode({message = "Hello, World!"}))';
             content_by_lua 'ngx.print(encode({message = "Hello, World!"}))';
         }
         }
+        location /fortunes {
+            default_type "text/html; charset=UTF-8";
+            content_by_lua 'app.fortunes(ngx)';
+        }
+        location /db {
+            default_type "application/json";
+            content_by_lua 'app.db(ngx)';
+        }
         location / {
         location / {
-            content_by_lua 'require("app")(ngx)';
+            default_type "application/json";
+            content_by_lua 'app.queries(ngx)';
         }
         }
     }
     }
 }
 }

+ 1 - 1
frameworks/PHP/codeigniter/install.sh

@@ -9,4 +9,4 @@ fw_depends php nginx composer
 
 
 ${PHP_HOME}/bin/php ${COMPOSER_HOME}/composer.phar install \
 ${PHP_HOME}/bin/php ${COMPOSER_HOME}/composer.phar install \
   --no-interaction --working-dir $TROOT \
   --no-interaction --working-dir $TROOT \
-  --no-progress --optimize-autoloader 
+  --no-progress --optimize-autoloader

+ 63 - 0
frameworks/PHP/cygnite-php-framework/.gitignore

@@ -0,0 +1,63 @@
+
+
+#Build System
+**/builds/*
+
+#bower
+/bower_components
+
+#Binary files
+/bin/
+
+#Grunt
+/node_modules/*
+
+# Composer
+/vendor/
+composer.phar
+composer.lock
+
+# Code Coverage
+build/coverage/*
+
+# always-ignore extensionsalways-ignore extensions
+*.diff
+*.err
+*.orig
+*.log
+*.rej
+*.swo
+*.swp
+*.vi
+*~
+*.sass-cache
+
+# OS or Editor folders
+.DS_Store
+Thumbs.db
+.cache
+.project
+.settings
+.tmproj
+*.esproj
+nbproject
+
+# Dreamweaver added files
+_notes
+dwsync.xml
+
+# Komodo
+*.komodoproject
+.komodotools
+
+# Folders to ignore
+.hg
+.svn
+.CVS
+intermediate
+publish
+.idea
+
+
+#Arcanist
+.arcconfig

+ 28 - 0
frameworks/PHP/cygnite-php-framework/.htaccess

@@ -0,0 +1,28 @@
+# Apache configuration file
+# http://httpd.apache.org/docs/2.2/mod/quickreference.html
+
+# Note: ".htaccess" files are an overhead for each request. This logic should
+# be placed in your Apache config whenever possible.
+# http://httpd.apache.org/docs/2.2/howto/htaccess.html
+
+# Turning on the rewrite engine is necessary for the following rules and
+# features. "+FollowSymLinks" must be enabled for this to work symbolically.
+
+<IfModule mod_rewrite.c>
+	Options +FollowSymLinks
+	RewriteEngine On
+	php_value safe_mode off
+</IfModule>
+
+# For all files not found in the file system, reroute the request to the
+# "index.php" front controller, keeping the query string intact
+
+<IfModule mod_rewrite.c>
+	RewriteCond %{REQUEST_FILENAME} !-f
+	RewriteCond %{REQUEST_FILENAME} !-d
+	RewriteRule ^(.*)$ index.php/$1 [L]
+	
+</IfModule>
+
+Order allow,deny
+Allow from all

+ 8 - 0
frameworks/PHP/cygnite-php-framework/.travis.yml

@@ -0,0 +1,8 @@
+language: php
+
+php:
+  - 5.4
+  - 5.5
+
+before_script:
+  - "composer install"

+ 20 - 0
frameworks/PHP/cygnite-php-framework/LICENSE

@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2013-2014 Cygnite Framework <Sanjoy Dey>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 54 - 0
frameworks/PHP/cygnite-php-framework/README.md

@@ -0,0 +1,54 @@
+Skeleton Application Using Cygnite PHP Framework
+------------------------------------------------------------------
+
+[![Latest Stable Version](https://poser.pugx.org/cygnite/cygnite-application/v/stable.svg)](https://packagist.org/packages/cygnite/cygnite-application) [![Total Downloads](https://poser.pugx.org/cygnite/cygnite-application/downloads.svg)](https://packagist.org/packages/cygnite/cygnite-application) [![Latest Unstable Version](https://poser.pugx.org/cygnite/cygnite-application/v/unstable.svg)](https://packagist.org/packages/cygnite/cygnite-application) [![License](https://poser.pugx.org/cygnite/cygnite-application/license.svg)](https://packagist.org/packages/cygnite/cygnite-application)
+
+Sample skeleton application using the Cygnite MVC layer - http://www.cygniteframework.com
+
+>  Note: This repository contains the skeleton application of the Cygnite Framework. If you would like to contribute
+on Cygnite Framework, please visit the core [repository](https://github.com/cygnite/framework).
+
+Installation
+--------------
+The best way to install Cygnite Framework is to download composer.phar from http://getcomposer.org/ to your local directory or to use globally on your system move it to
+usr/local/bin. For windows users please download and install composer setup.
+
+You may install Cygnite Framework either simply downloading skeleton application from github repository or install via composer. Composer installation is more convenient.
+
+
+Composer: Create Project
+--------------------------------
+Create your project from terminal by simply entering below command.
+
+    composer create-project cygnite/cygnite-application cygnite --prefer-dist
+                                        or
+    composer.phar create-project cygnite/cygnite-application cygnite --prefer-dist
+
+That's all you are ready to build your awesome application.
+
+
+##Contribute -
+------------------
+-> Getting bored with the same kind of development all time?
+
+-> Would you like to be well recognised by professionals ?
+
+-> Do you want to learn something interesting and showcase your skills to grab better position ?
+
+You are at right place. We welcome you to participate on Cygnite Framework development or its documentation.
+
+Contribute on Cygnite Framework development and grow with us. Join the team, learn, get help and help others, find, report bugs, send us your feedback,
+send your wishlist for new features, write and send us patches for Cygnite Framework.
+
+
+##Getting Started with Cygnite -
+-----------------------------------------
+i.  Make sure you have GitHub Account.
+
+ii. Clearly describe the issue you find to fix shortly.
+
+iii. Create a branch where you would like to place your changes and send the patches to us.
+
+iv.  Fork cygnite/framework repository on GitHub.
+
+v. Please follow the PSR coding standard as followed  while contributing or please request for coding standard to follow.

+ 1 - 0
frameworks/PHP/cygnite-php-framework/apps/.htaccess

@@ -0,0 +1 @@
+Deny from all

+ 0 - 0
frameworks/PHP/cygnite-php-framework/apps/components/authentication/.gitkeep


+ 0 - 0
frameworks/PHP/cygnite-php-framework/apps/components/form/.gitkeep


+ 235 - 0
frameworks/PHP/cygnite-php-framework/apps/configs/application.php

@@ -0,0 +1,235 @@
+<?php
+if (!defined('CF_SYSTEM')) {
+    exit('External script access not allowed');
+}
+/**
+ *  Cygnite Framework
+ *  Global Configuration Settings
+ *
+ *  An open source application development framework for PHP 5.3x or newer
+ *
+ *   License
+ *
+ *   This source file is subject to the MIT license that is bundled
+ *   with this package in the file LICENSE.txt.
+ *   http://www.cygniteframework.com/license.txt
+ *   If you did not receive a copy of the license and are unable to
+ *   obtain it through the world-wide-web, please send an email
+ *   to [email protected] so I can send you a copy immediately.
+ *
+ * @package            :  Apps
+ * @subpackages        :  Configs
+ * @filename           :  application
+ * @description        :  You can set your all your global configurations here.
+ * @author             :  Sanjoy Dey
+ * @copyright          :  Copyright (c) 2013 - 2014,
+ * @link               :  http://www.cygniteframework.com
+ * @since              :  Version 1.0
+ * @filesource
+ * @warning            :  If you don't protect this directory from direct web access,
+ *                     anybody will be able to see your configuration and settings.
+ *
+ *
+ */
+
+return array(
+    /**
+     *--------------------------------------------------------------------------
+     * Your Application Base URL
+     *--------------------------------------------------------------------------
+     * The base URL used to import your application assets in your web page.
+     * Based on base url we will perform page redirect and other internal
+     * functionality.
+     *
+     */
+    'base_path' => '',
+    /*
+    *--------------------------------------------------------------------------
+    * Your Application Default Controller
+    *--------------------------------------------------------------------------
+    * Set your application default controller here. Default controller
+    * will be called when you try to access cygnite application.
+    */
+    'default_controller' => 'Home',
+    /*
+    *--------------------------------------------------------------------------
+    * Your Application Default Method
+    *--------------------------------------------------------------------------
+    * You can set your application default method here. By default we
+    * we will call index method of your controller.
+    * You can also change the default method.
+    *
+    */
+    'default_method' => 'index',
+
+    /*
+    *---------------------------------------------------------------------------
+    * Set Application Environment
+    *---------------------------------------------------------------------------
+    * You can set your application environment in order to handle errors and exceptions.
+    * Development mode all errors are turned on. So that you can able to fix all issues easily.
+    * Errors will be turned off in production server mode.
+    *
+    * Example :
+    * environment => 'development/production'
+    */
+    'environment' => 'production', //Errors are turned on in development environment
+
+    /*
+    *--------------------------------------------------------------------------
+    * Your Application Character Encoding
+    *--------------------------------------------------------------------------
+    * Here you can set your application default character encoding . This encoding
+    * will be used by the Str, Text, Form, and any other classes that need
+    *  to know what type of encoding to use for your generous application.
+    *
+    */
+    'encoding' => 'UTF-8',
+    /*
+    *--------------------------------------------------------------------------
+    * Your Application Language
+    *--------------------------------------------------------------------------
+    * You can set your application default language here. Language library will
+    * will take care rest.
+    */
+    'language' => 'en',
+    /*
+    *--------------------------------------------------------------------------
+    * Application Timezone
+    *--------------------------------------------------------------------------
+    * You can set your application timezone here.This timezone will
+    * be used when cygnite need date time or any internal features.
+    *
+    */
+    'timezone' => 'UTC',
+    /*
+    *--------------------------------------------------------------------------
+    *  Application Encryption key
+    *--------------------------------------------------------------------------
+    * Set your encryption key here. You must set your encryption key here in order to
+    * use cygnite secure encryption and session library. We used php mcrypt extension
+    * library for encryption library. So please check whether you have else please activate
+    * to work with secure encryption and session library.
+    */
+    'cf_encryption_key' => 'cygnite-shaXatBNHQ4',
+    /*
+    *--------------------------------------------------------------------------
+    * Benchmark Your Application
+    *--------------------------------------------------------------------------
+    * Enable profiling as True if you wish to benchmark your application. You can
+    * make it FALSE to deactivate profiling. Cygnite will take care rest.
+    */
+    'enable_profiling' => false,
+    /*
+    *--------------------------------------------------------------------------
+    * ************Your Application Cache Config*************
+    *--------------------------------------------------------------------------
+    * You can enable cache here (example: TRUE/FALSE). Cygnite have
+    * three type of cache driver FileCache, Memcache, APC to boost your
+    * application performace. Follow user guide for usages.
+    */
+    'enable_cache' => false,
+    /*
+    *---------------------------------------------------------------------------
+    * Cache Name
+    *---------------------------------------------------------------------------
+    * Set your cache name here to generate cache file name if you are
+    * using cygnite file caching technique.
+    */
+    'cache_name' => 'file.cache',
+    /*
+    *---------------------------------------------------------------------------
+    * Cache Extension
+    *---------------------------------------------------------------------------
+    * Set your cache extension here. Cygnite will take care of rest. Cache will
+    * store with same extension which you will provide here.
+    *
+    */
+    'cache_extension' => '.cache',
+    /*
+    *---------------------------------------------------------------------------
+    * Cache Type
+    *---------------------------------------------------------------------------
+    * Set your cache type here. Cygnite will take care of rest.
+    *
+    */
+    'cache_type' => 'file',
+    /*
+    *---------------------------------------------------------------------------
+    * Cache Storage Location
+    *---------------------------------------------------------------------------
+    * Set your cache file storage location here. By default we are using
+    * temp/cache.
+    *
+    */
+    'cache_directory' => 'temp.cache', //Default value is none
+
+    /**
+     *---------------------------------------------------------------------------
+     * Cygnite Application Logs
+     *---------------------------------------------------------------------------
+     * If you enable debugger will generate error logs into apps/temp/logs/
+     *
+     */
+    'enable_logging' => false,
+    /*
+    *---------------------------------------------------------------------------
+    * Logs File Name
+    *---------------------------------------------------------------------------
+    * Set your log file name here. Your applications logs will generate
+    * by cygnite engine and store as filename you provide here.
+    *
+    */
+    //'log_file_name'                => 'application_logs' ,
+    /*
+    *---------------------------------------------------------------------------
+    * Logs Storage Location
+    *---------------------------------------------------------------------------
+    * Set your log storage location here. By default we are using
+    * temp/logs.
+    *
+    */
+    'log_path' => 'apps.temp.logs',
+
+    /**
+     * Enable error emailing. When any error occur in production
+     * Mode email will trigger. Set true or false
+     */
+    'enable_error_emailing' => false,
+
+    /*
+     * Email Configurations
+     */
+    'email_configurations' => array(
+
+        'protocol' => 'smtp',
+
+        'smtp' => array(
+            'host' => 'smtp.gmail.com',
+            'username' => 'your gmail id',
+            'password' => 'your password',
+            'port' => '465',
+            'encryption' => 'ssl',
+        ),
+        'sendmail' => array(
+            'path' => '/usr/sbin/exim -bs'
+        ),
+
+    ),
+    'params' => array(
+
+        /*
+        | You can define your params here.
+        | All your params defined here has access
+        | globally in your application.
+        */
+        'admin_email' => '[email protected]',
+
+        /*
+        | We will make use of email address to send error log
+        | when application is in production mode.
+        |
+        */
+        'log_email' => '[email protected]',
+    ),
+);

+ 35 - 0
frameworks/PHP/cygnite-php-framework/apps/configs/autoload.php

@@ -0,0 +1,35 @@
+<?php
+/**
+ * This file is part of the Cygnite package.
+ *
+ * (c) Sanjoy Dey <[email protected]>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Cygnite\Foundation;
+
+if (!defined('CF_SYSTEM')) {
+    exit('External script access not allowed');
+}
+
+return array(
+    /*---------------------------------------------------------------------------
+    * Register all your directories to auto load your files.
+    *---------------------------------------------------------------------------
+    * You can specify multiple numbers of directories here to register on
+    * Cygnite Engine during runtime. Don't worry about the application
+    * performance because all libraries are lazy loaded. But filename,
+    * class name and file should be same, StudlyCaps.
+    *
+    *  Specify your directory path here. That's all. Cygnite will
+    *  take care of rest.
+    */
+    Application::instance()->registerDirectories(
+        array(
+            'apps.controllers',
+            'apps.models',
+            'apps.configs.definitions'
+        )
+    )
+);

+ 55 - 0
frameworks/PHP/cygnite-php-framework/apps/configs/database.php

@@ -0,0 +1,55 @@
+<?php
+/*
+ * This file is part of the Cygnite package.
+ *
+ * (c) Sanjoy Dey <[email protected]>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Cygnite\Database;
+
+if (!defined('CF_SYSTEM')) {
+    exit('External script access not allowed');
+}
+
+/**
+ * Initialize your database configurations settings here.
+ * You can connect with multiple database on the fly.
+ * Don't worry about performance Cygnite will not
+ * connect with database until first time you need your
+ * connection to interact with database.
+ * Specify your database name and table name in model to
+ * do crude operations.
+ *
+ * Please protect this file to have maximum security.
+ */
+Configuration::initialize(
+    function ($config) {
+        $config->default = 'db';
+        $config->setConfig(
+            array(
+                'db' => array(
+                    'driver' => 'mysql',
+                    'host' => '127.0.0.1',
+                    'port' => '',
+                    'database' => 'hello_world',
+                    'username' => 'benchmarkdbuser',
+                    'password' => 'benchmarkdbpass',
+                    'charset' => 'utf8'
+                )
+                /*'db1' => array(
+                    'driver' => 'mysql',
+                    'host' => 'localhost',
+                    'port' => '',
+                    'database' => '',
+                    'username' => '',
+                    'password' => '',
+                    'charset' => 'utf8'
+                )*/
+            )
+        );
+    }
+);
+
+

+ 77 - 0
frameworks/PHP/cygnite-php-framework/apps/configs/definitions/DefinitionManager.php

@@ -0,0 +1,77 @@
+<?php
+namespace Apps\Configs\Definitions;
+
+if (!defined('CF_SYSTEM')) {
+    exit('External script access not allowed');
+}
+/**
+ *  Cygnite Framework
+ *  Database Configuration Settings
+ *
+ *  An open source application development framework for PHP 5.3x or newer
+ *
+ *   License
+ *
+ *   This source file is subject to the MIT license that is bundled
+ *   with this package in the file LICENSE.txt.
+ *   http://www.cygniteframework.com/license.txt
+ *   If you did not receive a copy of the license and are unable to
+ *   obtain it through the world-wide-web, please send an email
+ *   to [email protected] so I can send you a copy immediately.
+ *
+ *@package               : Apps
+ *@subpackages           : Configurations
+ *@filename              : DefinitionManager.php
+ *@description           : Define all your property dependencies. Cygnite will
+ *                         inject your dependency at run time.
+ *@author                : Sanjoy Dey
+ *@copyright             : Copyright (c) 2013 - 2014,
+ *@link	                 : http://www.cygniteframework.com
+ *@since	             : Version 1.2
+ *@filesource
+ *
+ */
+
+ class DefinitionManager
+ {
+
+   /**
+      * Set controller property dependencies here.
+      * Cygnite will inject all your dependencies at runtime
+      *
+      * @return array
+      *  <code>
+      *   return
+      *     array(
+      *          'HomeController' => array(
+      *              'service' => 'apps.extensions.general',
+      *              'api' => 'apps.extensions.api'
+      *           ),
+      *          'ProductsController' => array(
+      *             'social' => 'apps.extensions.social-share',
+      *          ),
+      *      );
+      *  </code>
+      *
+      */
+     public function getPropertyDependencies()
+     {
+        return array();
+     }
+
+     /**
+      *
+      * @return type
+       *  <code>
+      *   return
+      *     array(
+      *          'GeneralInterface' => '\\Apps\\Extensions\\General',
+      *          'ORM' => '\\Cygnite\\Database\\ActiveRecord',
+      *      );
+      *  </code>
+      */
+     public function registerAlias()
+     {
+         return array();
+     }
+ }

+ 69 - 0
frameworks/PHP/cygnite-php-framework/apps/configs/migration.php

@@ -0,0 +1,69 @@
+<?php
+namespace Cygnite\Database;
+
+/**
+ *  Cygnite Framework
+ *  Database Migration Configuration Settings
+ *
+ *  An open source application development framework for PHP 5.3x or newer
+ *
+ *   License
+ *
+ *   This source file is subject to the MIT license that is bundled
+ *   with this package in the file LICENSE.txt.
+ *   http://www.cygniteframework.com/license.txt
+ *   If you did not receive a copy of the license and are unable to
+ *   obtain it through the world-wide-web, please send an email
+ *   to [email protected] so I can send you a copy immediately.
+ *
+ *@package               : Apps
+ *@subpackages           : Database Migration Configurations
+ *@filename              : migration.php
+ *@description           : You can set your session configurations here.
+ *@author                : Sanjoy Dey
+ *@copyright             : Copyright (c) 2013 - 2014,
+ *@link	                 : http://www.cygniteframework.com
+ *@since	             : Version 1.2
+ *@filesource
+ *@warning               : If you don't protect this directory from direct web access,
+ * anybody will be able to see your database configuration and settings.
+ *
+ *
+ */
+
+if (!defined('CF_SYSTEM')) {
+    exit('External script access not allowed');
+}
+
+/**
+ * Initialize your database configurations settings here.
+ * You can connect with multiple database on the fly.
+ * Don't worry about performance Cygnite will not
+ * connect with database until first time you need your
+ * connection to interact with database.
+ * Specify your database name and table name in model to
+ * do crude operations.
+ *
+ * <code>
+ * 'connection'  => 'your-database',
+ * 'migration_path' => 'migration-directory',
+ * 'migration_table' => 'migration-table-name',
+ *
+ * </code>
+ *
+ * Example :
+ * cd console/bin
+ * php cygnite migrate:init create_products_table 
+ * php cygnite migrate
+ */
+
+
+return array(
+    'connection' => 'cygnite', //If you don't specify your connection name Cygnite will take default database 
+    //connection to generate your migrations
+
+    'migration_path' => 'apps.migrations',
+
+    'migration_table' => 'migrations',
+
+);

+ 27 - 0
frameworks/PHP/cygnite-php-framework/apps/configs/services.php

@@ -0,0 +1,27 @@
+<?php
+use Cygnite\Foundation\Application as App;
+
+if (!defined('CF_SYSTEM')) {
+    exit('External script access not allowed');
+}
+
+// Register all service provider
+App::service(function ($app)
+{
+    // Add multiple Service Provider into the array
+    /*
+     $app->registerServiceProvider(
+        array(
+            "Apps\\Services\\Payment\\ApiServiceProvider",
+        )
+    );
+	
+    // Use Controller as Service manual configuration
+    $app['user.controller'] = function () use($app)
+    {
+        return new \Apps\Controllers\HelloController(new \Cygnite\Mvc\Controller\ServiceController, $app);
+    }; 
+	// OR 
+	// Controller as Service automatic configuration
+    $app->setServiceController('hello.controller', '\Application\Controllers\HelloController');*/
+});

+ 105 - 0
frameworks/PHP/cygnite-php-framework/apps/configs/session.php

@@ -0,0 +1,105 @@
+<?php
+if (!defined('CF_SYSTEM')) {
+    exit('External script access not allowed');
+}
+/**
+ * Cygnite PHP Framework
+ *
+ * Session Configuration
+ *
+ * @author Sanjoy Dey <[email protected]>
+ */
+
+return array(
+
+    /**
+     *----------------------------------------------------------
+     * Session Driver
+     *----------------------------------------------------------
+     * Set session driver to use native session or database
+     * based session. Just provide the driver as "native" or
+     * "database". Cygnite will take care of next.
+     */
+    'driver' => 'native', // native, database
+
+    /**
+     *----------------------------------------------------------
+     * Session Name
+     *----------------------------------------------------------
+     * Set your session name, else cygnite will use default name
+     */
+    'session_name'  => 'cf_secure_session',
+
+    /**
+     *----------------------------------------------------------
+     * Session Storage Path
+     *----------------------------------------------------------
+     * Leave it as default as it will store into the default session
+     * directory.
+     */
+    'path' => 'default',
+
+    /**
+     *----------------------------------------------------------
+     * Database For Session Storage
+     *----------------------------------------------------------
+     * Set the database name if you are using database based session
+     * in order to store session.
+     *
+     * Change database name below to use session database driver
+     */
+    'database_name' => 'cygnite',
+
+    /**
+     *----------------------------------------------------------
+     * Setting Table Name For Session Storage
+     *----------------------------------------------------------
+     * Provide table name if you are using database based session.
+     * By default "cf_sessions" is the table to store all session
+     * into table.
+     */
+    'table' => 'cf_sessions',
+
+    /**
+     *----------------------------------------------------------
+     * Use Session Cookie
+     *----------------------------------------------------------
+     * Configure to use session cookie or not
+     */
+    'use_session_cookie' => false,
+
+    /**
+     *----------------------------------------------------------
+     * Session Cookie Name
+     *----------------------------------------------------------
+     * If you are using session cookie then provide the name here else
+     * leave it blank.
+     */
+    'session_cookie_name' => '',
+
+    /**
+     *----------------------------------------------------------
+     * HTTP Only
+     *----------------------------------------------------------
+     * Configure to set httponly for cookie params
+     */
+    'httponly' => true,
+
+    /**
+     * --------------------------------------------------------
+     *  Set Session Time out
+     * --------------------------------------------------------
+     * Currently not implemented, you can change the session
+     * timeout in php.ini configuration file
+     */
+    'timeout' => 1440,
+
+    /**
+     *----------------------------------------------------------
+     * Secure Session
+     *----------------------------------------------------------
+     * You may leave it as false or true to use secure session
+     * By default cygnite provides most security to the session.
+     */
+    'secure' => false,
+);

+ 94 - 0
frameworks/PHP/cygnite-php-framework/apps/controllers/BenchController.php

@@ -0,0 +1,94 @@
+<?php
+namespace Apps\Controllers;
+
+use Cygnite\Mvc\Controller\AbstractBaseController;
+use Apps\Models\Fortune;
+use Apps\Models\World;
+
+class BenchController extends AbstractBaseController
+{
+    protected $templateEngine = false;
+
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    public function indexAction()
+    {
+        echo 'Hello World!';
+    }
+
+    public function dbAction()
+    {
+        $worlds = $arr = array();
+        $world = null;
+        $queries = 1;
+
+        $worlds = $this->getWorldsInfo($queries);
+        $worlds = $worlds[0];
+
+        header('Content-type: application/json');
+        echo json_encode($worlds);
+    }
+
+    private function getWorldsInfo($queries)
+    {
+        $world = null;
+        $worlds = $arr = array();
+
+        for ($i = 0; $i < $queries; ++$i) {
+            $world = World::find(mt_rand(1, 10000));
+            $arr['id'] = (int) $world->id;
+            $arr['randomNumber'] = (int) $world->randomnumber;
+            $worlds[] = $arr;
+        }
+
+        return $worlds;
+    }
+
+    public function queriesAction($queries = 1)
+    {
+        $queries = intval($queries);
+        if ($queries < 1 ) {
+            $queries = 1;
+        } elseif ($queries > 500) {
+            $queries = 500;
+        }
+
+        $worlds = array();
+        $worlds = $this->getWorldsInfo($queries);
+
+        header('Content-type: application/json');
+        echo json_encode($worlds);
+    }
+
+    public function fortunesAction()
+    {
+        $fortuneCollection = array();
+        $fortuneCollection = Fortune::all();
+        $fortunes = $fortuneCollection->asArray();
+
+        $runtimeFortune = new Fortune();
+        $runtimeFortune->id = 0;
+        $runtimeFortune->message = 'Additional fortune added at request time.';
+
+        $fortunes[] = $runtimeFortune;
+
+        usort($fortunes, function($left, $right) {
+
+            if ($left->message === $right->message) {
+                return 0;
+            } else if ($left->message > $right->message) {
+                return 1;
+            } else {
+                return -1;
+            }
+
+        });
+
+        $this->render('fortunes', array(
+                'fortunes' => $fortunes
+        ));
+    }
+}

+ 80 - 0
frameworks/PHP/cygnite-php-framework/apps/controllers/HomeController.php

@@ -0,0 +1,80 @@
+<?php
+namespace Apps\Controllers;
+
+use Cygnite\Foundation\Application;
+use Cygnite\Mvc\Controller\AbstractBaseController;
+
+class HomeController extends AbstractBaseController
+{
+    /**
+    * --------------------------------------------------------------------------
+    * The Default Controller
+    *--------------------------------------------------------------------------
+    *  This controller respond to uri beginning with home and also
+    *  respond to root url like "home/index"
+    *
+    * Your GET request of "home/index" will respond like below -
+    *
+    *      public function indexAction()
+    *     {
+    *            echo "Cygnite : Hellow ! World ";
+    *     }
+    * Note: By default cygnite doesn't allow you to pass query string in url, which
+    * consider as bad url format.
+    *
+    * You can also pass parameters into the function as below-
+    * Your request to  "home/form/2134" will pass to
+    *
+    *      public function formAction($id = ")
+    *      {
+    *             echo "Cygnite : Your user Id is $id";
+    *      }
+    * In case if you are not able to access parameters passed into method
+    * directly as above, you can also get the uri segment
+    *  echo Url::segment(3);
+    *
+    * That's it you are ready to start your awesome application with Cygnite Framework.
+    *
+    */
+
+    protected $layout = 'layout.home';
+
+    protected $templateEngine = false;
+
+   // protected $templateExtension = '.html.twig';
+
+   //protected $autoReload = true;
+     /*
+     * Your constructor.
+     * @access public
+     *
+     */
+    public function __construct()
+    {
+        parent::__construct();
+
+    }
+
+    /**
+     * Default method for your controller. Render welcome page to user.
+     * @access public
+     *
+     */
+   public function indexAction()
+   {
+       $this->render('welcome', array('title' => 'Welcome to Cygnite Framework'));
+   }
+   
+   public function hmvcAction($id)
+   {
+        //We are calling HMVC widget and return response
+		$widgetResponse = $this->call('modules.admin.controllers.user@index', array('id' => $id));
+		
+		//You should enable layout in order to access variable into view page
+       $this->render('application', array(
+                'messege' => 'Welcome to Cygnite framework',
+                'userwidget' => $widgetResponse
+        ));  
+   }
+
+}//End of your home controller

+ 0 - 0
frameworks/PHP/cygnite-php-framework/apps/database/.gitkeep


+ 0 - 0
frameworks/PHP/cygnite-php-framework/apps/database/migrations/.gitkeep


+ 0 - 0
frameworks/PHP/cygnite-php-framework/apps/extensions/.gitkeep


部分文件因文件數量過多而無法顯示