Browse Source

Merge pull request #1855 from k-r-g/clojure-updates

Compojure and http-kit: Update dependencies and sync implemetations
Nate 9 years ago
parent
commit
741cd6d25b

+ 4 - 17
frameworks/Clojure/compojure/README.md

@@ -14,20 +14,7 @@ This is the Compojure portion of a [benchmarking test suite](../) comparing a va
 The dependencies are documented in [project.clj](hello/project.clj),
 but the main ones are:
 
-* [Clojure 1.5.1](http://clojure.org/)
-* [Compojure 1.1.5](https://github.com/weavejester/compojure)
-* [Ring-JSON 0.2.0](https://github.com/ring-clojure/ring-json), which in turn uses [Cheshire](https://github.com/dakrone/cheshire), which in turn uses [Jackson](http://jackson.codehaus.org/)
-* [Korma 0.3.0-RC5](http://sqlkorma.com/)
-
-## Test URLs
-### JSON Encoding Test
-
-http://localhost/hello-compojure-standalone/json
-
-### Data-Store/Database Mapping Test
-
-http://localhost/hello-compojure-standalone/db
-
-### Variable Query Test
-
-http://localhost/hello-compojure-standalone/db/2
+* [Clojure 1.7.0](http://clojure.org/)
+* [Compojure 1.4.0](https://github.com/weavejester/compojure)
+* [Ring-JSON 0.4.0](https://github.com/ring-clojure/ring-json), which in turn uses [Cheshire](https://github.com/dakrone/cheshire), which in turn uses [Jackson](http://jackson.codehaus.org/)
+* [Korma 0.4.2](http://sqlkorma.com/)

+ 6 - 4
frameworks/Clojure/compojure/benchmark_config.json

@@ -5,9 +5,9 @@
       "setup_file": "setup",
       "json_url": "/compojure/json",
       "db_url": "/compojure/db",
-      "query_url": "/compojure/db/",
+      "query_url": "/compojure/queries/",
       "update_url": "/compojure/updates/",
-      "fortune_url": "/compojure/fortune-hiccup",
+      "fortune_url": "/compojure/fortunes",
       "plaintext_url": "/compojure/plaintext",
       "port": 8080,
       "approach": "Realistic",
@@ -26,8 +26,10 @@
     },
     "raw": {
       "setup_file": "setup",
-      "db_url": "/compojure/dbraw",
-      "query_url": "/compojure/dbraw/",
+      "db_url": "/compojure/raw/db",
+      "query_url": "/compojure/raw/queries/",
+      "update_url": "/compojure/raw/updates/",
+      "fortune_url": "/compojure/raw/fortunes",
       "port": 8080,
       "approach": "Realistic",
       "classification": "Micro",

+ 12 - 10
frameworks/Clojure/compojure/hello/project.clj

@@ -1,16 +1,18 @@
 (defproject hello "compojure"
-  :description "JSON/Database tests"
+  :description "FrameworkBenchmarks test implementations"
   :url "http://localhost:3000/"
-  :dependencies [[org.clojure/clojure "1.5.1"]
-                 [compojure "1.1.6"]
-                 [ring/ring-json "0.2.0"]
-                 [korma "0.3.0-RC6"]
+  :min-lein-version "2.0.0"
+  :dependencies [[org.clojure/clojure "1.7.0"]
+                 [compojure "1.4.0"]
+                 [ring/ring-json "0.4.0"]
+                 [korma "0.4.2"]
                  [log4j "1.2.15" :exclusions [javax.mail/mail javax.jms/jms com.sun.jdmk/jmxtools com.sun.jmx/jmxri]]
-                 [mysql/mysql-connector-java "5.1.6"]
-                 [org.clojure/java.jdbc "0.3.0-alpha1"]
+                 [mysql/mysql-connector-java "5.1.38"]
+                 [org.clojure/java.jdbc "0.3.7"]
                  [c3p0/c3p0 "0.9.1.2"]
-                 [hiccup "1.0.4"]]
-  :plugins [[lein-ring "0.8.10"]]
+                 [hiccup "1.0.5"]]
+  :plugins [[lein-ring "0.9.7"]]
   :ring {:handler hello.handler/app}
   :profiles
-  {:dev {:dependencies [[ring-mock "0.1.5"]]}})
+  {:dev {:dependencies [[javax.servlet/servlet-api "2.5"]
+                        [ring/ring-mock "0.3.0"]]}})

+ 132 - 117
frameworks/Clojure/compojure/hello/src/hello/handler.clj

@@ -1,8 +1,8 @@
 (ns hello.handler
   (:import com.mchange.v2.c3p0.ComboPooledDataSource)
   (:use compojure.core
+        ring.middleware.content-type
         ring.middleware.json
-        ring.util.response
         korma.db
         korma.core
         hiccup.core
@@ -10,55 +10,41 @@
         hiccup.page)
   (:require [compojure.handler :as handler]
             [compojure.route :as route]
-            [clojure.java.jdbc :as jdbc]
-            [clojure.java.jdbc.sql :as sql]))
+            [ring.util.response :as ring-resp]
+            [clojure.java.jdbc :as jdbc]))
 
-
-; 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
-                  }))
-
-
-; 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 run-queries
-  "Run the specified number of queries, return the results"
+(defn sanitize-queries-param
+  "Sanitizes the `queries` parameter. Clamps the value between 1 and 500.
+  Invalid (string) values become 1."
   [queries]
-  (flatten ; Make it a list of maps
-    (take queries ; Number of queries to run
-          (repeatedly get-world))))
-
+  (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)))
 
-; Database connection for java.jdbc "raw"
-; https://github.com/clojure/java.jdbc/blob/master/doc/clojure/java/jdbc/ConnectionPooling.md
+;; MySQL database connection
+(defdb db-mysql
+  (mysql {
+          :classname "com.mysql.jdbc.Driver"
+          :subprotocol "mysql"
+          :subname "//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"
+          :user "benchmarkdbuser"
+          :password "benchmarkdbpass"
+          ;;OPTIONAL KEYS
+          :delimiters "" ;; remove delimiters
+          :maximum-pool-size 256}))
+
+;; MySQL 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"
+   :subname "//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"
    :user "benchmarkdbuser"
    :password "benchmarkdbpass"})
 
-
 (defn pool
   [spec]
   (let [cpds (doto (ComboPooledDataSource.)
@@ -72,67 +58,70 @@
                (.setMaxIdleTime (* 3 60 60)))]
     {:datasource cpds}))
 
-
 (def pooled-db (delay (pool db-spec-mysql-raw)))
 
+(defn db-mysql-raw [] @pooled-db)
 
-(defn db-raw [] @pooled-db)
+;; Set up entity World and the database representation
+(defentity world
+  (pk :id)
+  (table :world)
+  (entity-fields :id :randomNumber) ; Default fields for select
+  (database db-mysql))
 
+(defn get-random-world-korma
+  "Query a random World record from the database"
+  []
+  (let [id (inc (rand-int 9999))] ; Num between 1 and 10,000
+    (select world
+            (where {:id id }))))
 
-(defn get-world-raw
+(defn run-queries
+  "Run query repeatedly, return an array"
+  [queries]
+  (flatten ; Make it a list of maps
+    (take queries ; Number of queries to run
+          (repeatedly get-random-world-korma))))
+
+(defn get-random-world-raw
   "Query a random World record from the database"
   []
   (let [id (inc (rand-int 9999))]
-    (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))))))
-
+    (jdbc/query (db-mysql-raw) [(str "select * from world where id = ?") id])))
 
 (defn run-queries-raw
-  "Run the specified number of queries, return the results"
+  "Run query repeatedly, return an array"
   [queries]
   (flatten ; Make it a list of maps
     (take queries
-          (repeatedly get-world-raw))))
+          (repeatedly get-random-world-raw))))
 
-
-(defn get-query-count
-  "Parse provided string value of query count, clamping values to between 1 and 500."
-  [queries]
-  (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)))
-
-
-; Set up entity World and the database representation
+;; Set up entity Fortune and the database representation
 (defentity fortune
   (pk :id)
   (table :fortune)
   (entity-fields :id :message)
-  (database db))
+  (database db-mysql))
 
-
-(defn get-all-fortunes
-  "Query all Fortune records from the database."
+(defn get-all-fortunes-korma
+  "Query all Fortune records from the database using Korma."
   []
   (select fortune
           (fields :id :message)))
 
+(defn get-all-fortunes-raw
+  "Query all Fortune records from the database using JDBC."
+  []
+  (jdbc/query (db-mysql-raw) [(str "select * from fortune")]))
 
 (defn get-fortunes
   "Fetch the full list of Fortunes from the database, sort them by the fortune
   message text, and then return the results."
-  []
-  (let [fortunes (conj (get-all-fortunes)
-                       {:id 0
-                        :message "Additional fortune added at request time."})]
-    (sort-by #(:message %) fortunes)))
-
+  [query-function]
+  (sort-by #(:message %)
+    (conj
+      (query-function)
+      { :id 0 :message "Additional fortune added at request time." })))
 
 (defn fortunes-hiccup
   "Render the given fortunes to simple HTML using Hiccup."
@@ -151,12 +140,11 @@
         [:td (escape-html (:message x))]])
      ]]))
 
-
-(defn update-and-persist
-  "Changes the :randomNumber of a number of world entities.
+(defn update-and-persist-korma
+  "Using Korma: 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)]
+(let [results (run-queries queries)]
     (for [w results]
       (update-in w [:randomNumber (inc (rand-int 9999))]
         (update world
@@ -164,80 +152,107 @@
                 (where {:id [:id w]}))))
     results))
 
+(defn update-and-persist-raw
+  "Using JDBC: 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))]
+        (jdbc/update! (db-mysql-raw) :world {:randomNumber (:randomNumber w)} ["id = ?" (:id w)])))
+    results))
 
 (def json-serialization
   "Test 1: JSON serialization"
-  (response {:message "Hello, World!"}))
-
+  (ring-resp/response {:message "Hello, World!"}))
 
 (def single-query-test
   "Test 2: Single database query"
-  (-> 1
-      (run-queries)
-      (first)
-      (response)))
-
+  (ring-resp/response (first (run-queries 1))))
 
-(defn multiple-query-test
+(defn multiple-queries-test
   "Test 3: Multiple database queries"
   [queries]
   (-> queries
-      (get-query-count)
+      (sanitize-queries-param)
       (run-queries)
-      (response)))
-
+      (ring-resp/response)))
 
 (def single-query-test-raw
   "Test 2: Single database query (raw)"
   (-> 1
       (run-queries-raw)
       (first)
-      (response)))
-
+      (ring-resp/response)))
 
-(defn multiple-query-test-raw
+(defn multiple-queries-test-raw
   "Test 3: Multiple database queries (raw)"
   [queries]
   (-> queries
-      (get-query-count)
+      (sanitize-queries-param)
       (run-queries-raw)
-      (response)))
-
+      (ring-resp/response)))
 
 (def fortune-test
   "Test 4: Fortunes"
-  (response (fortunes-hiccup (get-fortunes))))
-
+  (->
+    (get-fortunes get-all-fortunes-korma)
+    (fortunes-hiccup)
+    (ring-resp/response)
+    (ring-resp/content-type "text/html")
+    (ring-resp/charset "utf-8")))
+
+(def fortune-test-raw
+  "Test 4: Fortunes Raw"
+  (->
+    (get-fortunes get-all-fortunes-raw)
+    (fortunes-hiccup)
+    (ring-resp/response)
+    (ring-resp/content-type "text/html")
+    (ring-resp/charset "utf-8")))
 
 (defn db-updates
   "Test 5: Database updates"
   [queries]
   (-> queries
-      (get-query-count)
-      (update-and-persist)
-      (response)))
+      (sanitize-queries-param)
+      (update-and-persist-korma)
+      (ring-resp/response)))
+
+(defn db-updates-raw
+  "Test 5: Database updates Raw"
+  [queries]
+  (-> queries
+      (sanitize-queries-param)
+      (update-and-persist-raw)
+      (ring-resp/response)))
 
 (def plaintext
   "Test 6: Plaintext"
-  {:status 200
-   :headers {"Content-Type" "text/plain; charset=utf-8"}
-   :body "Hello, World!"})
-
+  (->
+    (ring-resp/response "Hello, World!")
+    (ring-resp/content-type "text/plain")))
 
+;; Define route handlers
 (defroutes app-routes
-  (GET "/"                 [] "Hello, World!")
-  (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 "/fortunes"         [] (response (get-fortunes))) ; Raw json of fortunes
-  (GET "/fortune-hiccup"   [] fortune-test)
-  (GET "/updates/:queries" [queries] (db-updates queries))
-  (GET "/plaintext"        [] plaintext)
+  (GET "/"                     [] "Hello, World!")
+  (GET "/plaintext"            [] plaintext)
+  (GET "/json"                 [] json-serialization)
+  (GET "/db"                   [] single-query-test)
+  (GET "/queries/:queries"     [queries] (multiple-queries-test queries))
+  (GET "/queries/"             [] (multiple-queries-test queries)) ; When param is omitted
+  (GET "/fortunes"             [] fortune-test)
+  (GET "/updates/:queries"     [queries] (db-updates queries))
+  (GET "/updates/"             [] (db-updates queries)) ; When param is omitted
+  (GET "/raw/db"               [] single-query-test-raw)
+  (GET "/raw/queries/:queries" [queries] (multiple-queries-test-raw queries))
+  (GET "/raw/queries/"         [] (multiple-queries-test-raw queries)) ; When param is omitted
+  (GET "/raw/fortunes"         [] fortune-test-raw)
+  (GET "/raw/updates/:queries" [queries] (db-updates-raw queries))
+  (GET "/raw/updates/"         [] (db-updates-raw queries)) ; When param is omitted
   (route/not-found "Not Found"))
 
-
 (def app
   "Format responses as JSON"
-  (wrap-json-response app-routes))
+  (-> app-routes
+      (wrap-json-response)))

+ 1 - 1
frameworks/Clojure/compojure/setup.sh

@@ -1,6 +1,6 @@
 #!/bin/bash
 
-fw_depends java7 resin leiningen
+fw_depends java8 resin leiningen
 
 sed -i 's|:subname "//.*:3306|:subname "//'"${DBHOST}"':3306|g' hello/src/hello/handler.clj
 

+ 1 - 1
frameworks/Clojure/compojure/source_code

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

+ 3 - 17
frameworks/Clojure/http-kit/README.md

@@ -14,21 +14,7 @@ This is the Compojure (using http-kit) portion of a [benchmarking test suite](..
 The dependencies are documented in [project.clj](hello/project.clj),
 but the main ones are:
 
-* [Clojure 1.5.1](http://clojure.org/)
-* [Compojure 1.1.5](https://github.com/weavejester/compojure)
-* [Ring-JSON 0.2.0](https://github.com/ring-clojure/ring-json), which in turn uses [Cheshire](https://github.com/dakrone/cheshire), which in turn uses [Jackson](http://jackson.codehaus.org/)
+* [Clojure 1.7.0](http://clojure.org/)
 * [http-kit](http://http-kit.org)
-* [dbcp.clj](https://github.com/http-kit/dbcp.clj)
-
-## Test URLs
-### JSON Encoding Test
-
-http://localhost/http-kit/json
-
-### Data-Store/Database Mapping Test
-
-http://localhost/http-kit/db
-
-### Variable Query Test
-
-http://localhost/http-kit/db/2
+* [Ring-JSON 0.4.0](https://github.com/ring-clojure/ring-json), which in turn uses [Cheshire](https://github.com/dakrone/cheshire), which in turn uses [Jackson](http://jackson.codehaus.org/)
+* [Korma 0.4.2](http://sqlkorma.com/)

+ 22 - 1
frameworks/Clojure/http-kit/benchmark_config.json

@@ -6,8 +6,8 @@
       "json_url": "/json",
       "db_url": "/db",
       "query_url": "/queries/",
-      "fortune_url": "/fortunes",
       "update_url": "/updates/",
+      "fortune_url": "/fortunes",
       "plaintext_url": "/plaintext",
       "port": 8080,
       "approach": "Realistic",
@@ -15,6 +15,27 @@
       "database": "MySQL",
       "framework": "http-kit",
       "language": "Clojure",
+      "orm": "Micro",
+      "platform": "http-kit",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "http-kit",
+      "notes": "",
+      "versus": ""
+    },
+    "raw": {
+      "setup_file": "setup",
+      "db_url": "/raw/db",
+      "query_url": "/raw/queries/",
+      "update_url": "/raw/updates/",
+      "fortune_url": "/raw/fortunes",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Platform",
+      "database": "MySQL",
+      "framework": "http-kit",
+      "language": "Clojure",
       "orm": "Raw",
       "platform": "http-kit",
       "webserver": "None",

+ 18 - 14
frameworks/Clojure/http-kit/hello/project.clj

@@ -1,23 +1,27 @@
-(defproject hello "compojure"
-  :description "JSON/Database tests"
-  :url "http://example.com/FIXME"
-  :dependencies [[org.clojure/clojure "1.5.1"]
-                 [compojure "1.1.5"]
-                 [ring/ring-json "0.2.0"]
+(defproject hello "http-kit"
+  :description "FrameworkBenchmarks test implementations"
+  :url "http://localhost:8080/"
+  :dependencies [[org.clojure/clojure "1.7.0"]
+                 [compojure "1.4.0"]
+                 [ring/ring-json "0.4.0"]
                  [org.clojure/tools.cli "0.2.1"]
-                 [http-kit/dbcp "0.1.0"]
-                 [http-kit "2.1.18"]
+                 [http-kit "2.1.19"]
+                 [korma "0.4.2"]
                  [log4j "1.2.15" :exclusions [javax.mail/mail javax.jms/jms com.sun.jdmk/jmxtools com.sun.jmx/jmxri]]
                  ; [ch.qos.logback/logback-classic "1.1.2" :exclusions [org.slf4j/slf4j-api]]
                  ; [org.slf4j/jul-to-slf4j "1.7.7"]
                  ; [org.slf4j/jcl-over-slf4j "1.7.7"]
                  ; [org.slf4j/log4j-over-slf4j "1.7.7"]
-                 [org.clojure/data.json "0.2.5"]
-                 [org.clojure/java.jdbc "0.3.6"]
-                 [korma "0.4.0"]
-                 [mysql/mysql-connector-java "5.1.6"]
-                 [hiccup "1.0.4"]]
+                 [ring/ring-jetty-adapter "1.4.0"]
+                 [mysql/mysql-connector-java "5.1.38"]
+                 [org.clojure/java.jdbc "0.3.7"]
+                 [c3p0/c3p0 "0.9.1.2"]
+                 [hiccup "1.0.5"]]
+  :plugins [[lein-ring "0.9.7"]]
+  :ring {:handler hello.handler/app}
   :main hello.handler
   :aot [hello.handler]
   :uberjar-name "http-kit-standalone.jar"
-  :profiles {:dev {:dependencies [[ring-mock "0.1.5"]]}})
+  :profiles
+  {:dev {:dependencies [[javax.servlet/servlet-api "2.5"]
+                        [ring/ring-mock "0.3.0"]]}})

+ 137 - 61
frameworks/Clojure/http-kit/hello/src/hello/handler.clj

@@ -13,90 +13,118 @@
   (:require [compojure.handler :as handler]
             [compojure.route :as route]
             [ring.util.response :as ring-resp]
-            [clojure.data.json :as json]
             [clojure.java.jdbc :as jdbc]))
 
+(defn sanitize-queries-param
+  "Sanitizes the `queries` parameter. Clamps the value between 1 and 500.
+  Invalid (string) values become 1."
+  [queries]
+  (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 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))
-
-
-;; MySQL connection
-(defdb mysql-db
+;; MySQL database connection
+(defdb db-mysql
   (mysql {
     :classname "com.mysql.jdbc.Driver"
     :subprotocol "mysql"
-    :subname "//127.0.0.1:3306/hello_world"
+    :subname "//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"
     :user "benchmarkdbuser"
     :password "benchmarkdbpass"
     ;;OPTIONAL KEYS
     :delimiters "" ;; remove delimiters
     :maximum-pool-size 256}))
 
+;; MySQL 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 "//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"
+   :user "benchmarkdbuser"
+   :password "benchmarkdbpass"})
+
+(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-mysql-raw [] @pooled-db)
 
 ;; Set up entity World and the database representation
 (defentity world
   (pk :id)
   (table :world)
-  (entity-fields :id :randomNumber) ;; Default fields for select
-  (database mysql-db))
-
+  (entity-fields :id :randomNumber) ; Default fields for select
+  (database db-mysql))
 
-(defn sanitize-queries-param
-  "Sanitizes the `queries` parameter. Caps the value between 1 and 500.
-  Invalid (stringy) values become 1"
-  [queries]
-  (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 random-world
+(defn get-random-world-korma
   "Query a random World record from the database"
   []
   (let [id (inc (rand-int 9999))] ; Num between 1 and 10,000
     (select world
             (where {:id id }))))
 
-
 (defn run-queries
-  "Run query repeatedly -- Always returns an array"
+  "Run query repeatedly, return an array"
+  [queries]
+  (flatten ; Make it a list of maps
+    (take queries ; Number of queries to run
+          (repeatedly get-random-world-korma))))
+
+(defn get-random-world-raw
+  "Query a random World record from the database"
+  []
+  (let [id (inc (rand-int 9999))]
+    (jdbc/query (db-mysql-raw) [(str "select * from world where id = ?") id])))
+
+(defn run-queries-raw
+  "Run query repeatedly, return an array"
   [queries]
-  (flatten (take queries (repeatedly random-world))))
+  (flatten ; Make it a list of maps
+    (take queries
+          (repeatedly get-random-world-raw))))
 
-; Set up entity Fortune and the database representation
+;; Set up entity Fortune and the database representation
 (defentity fortune
   (pk :id)
   (table :fortune)
   (entity-fields :id :message)
-  (database mysql-db))
-
+  (database db-mysql))
 
-(defn get-all-fortunes
-  "Query all Fortune records from the database."
+(defn get-all-fortunes-korma
+  "Query all Fortune records from the database using Korma."
   []
   (select fortune
           (fields :id :message)))
 
+(defn get-all-fortunes-raw
+  "Query all Fortune records from the database using JDBC."
+  []
+  (jdbc/query (db-mysql-raw) [(str "select * from fortune")]))
 
 (defn get-fortunes
   "Fetch the full list of Fortunes from the database, sort them by the fortune
   message text, and then return the results."
-  []
+  [query-function]
   (sort-by #(:message %)
     (conj
-      (get-all-fortunes)
+      (query-function)
       { :id 0 :message "Additional fortune added at request time." })))
 
-
 (defn fortunes-hiccup
   "Render the given fortunes to simple HTML using Hiccup."
   [fortunes]
@@ -114,14 +142,11 @@
         [:td (escape-html (:message x))]])
      ]]))
 
-
-(defn update-and-persist
-  "Changes the :randomNumber of a number of world entities.
+(defn update-and-persist-korma
+  "Using Korma: Changes the :randomNumber of a number of world entities.
   Persists the changes to sql then returns the updated entities"
   [queries]
-  (let [results (-> queries
-                    (sanitize-queries-param)
-                    (run-queries))]
+(let [results (run-queries queries)]
     (for [w results]
       (update-in w [:randomNumber (inc (rand-int 9999))]
         (update world
@@ -129,43 +154,80 @@
                 (where {:id [:id w]}))))
     results))
 
+(defn update-and-persist-raw
+  "Using JDBC: 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))]
+        (jdbc/update! (db-mysql-raw) :world {:randomNumber (:randomNumber w)} ["id = ?" (:id w)])))
+    results))
 
 (def json-serialization
   "Test 1: JSON serialization"
   (ring-resp/response {:message "Hello, World!"}))
 
-
 (def single-query-test
   "Test 2: Single database query"
   (ring-resp/response (first (run-queries 1))))
 
-
 (defn multiple-queries-test
   "Test 3: Multiple database queries"
   [queries]
   (-> queries
       (sanitize-queries-param)
       (run-queries)
-      (ring-resp/response)
-      (ring-resp/content-type "application/json")))
+      (ring-resp/response)))
+
+(def single-query-test-raw
+  "Test 2: Single database query (raw)"
+  (-> 1
+      (run-queries-raw)
+      (first)
+      (ring-resp/response)))
 
+(defn multiple-queries-test-raw
+  "Test 3: Multiple database queries (raw)"
+  [queries]
+  (-> queries
+      (sanitize-queries-param)
+      (run-queries-raw)
+      (ring-resp/response)))
 
 (def fortune-test
   "Test 4: Fortunes"
   (->
-    (get-fortunes)
+    (get-fortunes get-all-fortunes-korma)
     (fortunes-hiccup)
     (ring-resp/response)
-    (ring-resp/content-type "text/html")))
+    (ring-resp/content-type "text/html")
+    (ring-resp/charset "utf-8")))
 
+(def fortune-test-raw
+  "Test 4: Fortunes Raw"
+  (->
+    (get-fortunes get-all-fortunes-raw)
+    (fortunes-hiccup)
+    (ring-resp/response)
+    (ring-resp/content-type "text/html")
+    (ring-resp/charset "utf-8")))
 
 (defn db-updates
   "Test 5: Database updates"
   [queries]
   (-> queries
-      (update-and-persist)
+      (sanitize-queries-param)
+      (update-and-persist-korma)
       (ring-resp/response)))
 
+(defn db-updates-raw
+  "Test 5: Database updates Raw"
+  [queries]
+  (-> queries
+      (sanitize-queries-param)
+      (update-and-persist-raw)
+      (ring-resp/response)))
 
 (def plaintext
   "Test 6: Plaintext"
@@ -173,18 +235,32 @@
     (ring-resp/response "Hello, World!")
     (ring-resp/content-type "text/plain")))
 
-
 ;; Define route handlers
 (defroutes app-routes
-  (GET "/"                 [] "Hello, World!")
-  (GET "/json"             [] json-serialization)
-  (GET "/db"               [] single-query-test)
-  (GET "/queries/:queries" [queries] (multiple-queries-test queries))
-  (GET "/fortunes"         [] fortune-test)
-  (GET "/updates/:queries" [queries] (db-updates queries))
-  (GET "/plaintext"        [] plaintext)
+  (GET "/"                     [] "Hello, World!")
+  (GET "/plaintext"            [] plaintext)
+  (GET "/json"                 [] json-serialization)
+  (GET "/db"                   [] single-query-test)
+  (GET "/queries/:queries"     [queries] (multiple-queries-test queries))
+  (GET "/queries/"             [] (multiple-queries-test queries)) ; When param is omitted
+  (GET "/fortunes"             [] fortune-test)
+  (GET "/updates/:queries"     [queries] (db-updates queries))
+  (GET "/updates/"             [] (db-updates queries)) ; When param is omitted
+  (GET "/raw/db"               [] single-query-test-raw)
+  (GET "/raw/queries/:queries" [queries] (multiple-queries-test-raw queries))
+  (GET "/raw/queries/"         [] (multiple-queries-test-raw queries)) ; When param is omitted
+  (GET "/raw/fortunes"         [] fortune-test-raw)
+  (GET "/raw/updates/:queries" [queries] (db-updates-raw queries))
+  (GET "/raw/updates/"         [] (db-updates-raw queries)) ; When param is omitted
   (route/not-found "Not Found"))
 
+(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]}]
   ;; Format responses as JSON

+ 1 - 1
frameworks/Clojure/http-kit/setup.sh

@@ -1,6 +1,6 @@
 #!/bin/bash
 
-fw_depends leiningen java7
+fw_depends leiningen java8
 
 sed -i 's|:subname "//.*:3306|:subname "//'"${DBHOST}"':3306|g' hello/src/hello/handler.clj
 

+ 0 - 3
frameworks/Clojure/http-kit/source_code

@@ -1,5 +1,2 @@
 ./http-kit/hello/project.clj
-./http-kit/hello/src/
-./http-kit/hello/src/log4j.xml
-./http-kit/hello/src/hello
 ./http-kit/hello/src/hello/handler.clj