Browse Source

Merge remote-tracking branch 'upstream/master'

denka 10 years ago
parent
commit
c7ecbe76e2
100 changed files with 1560 additions and 736 deletions
  1. 1 2
      .travis.yml
  2. 1 1
      config/benchmark_profile
  3. 172 0
      config/cassandra/cassandra.init
  4. 6 0
      config/cassandra/cassandra.init.env
  5. 37 14
      config/cassandra/cassandra.yaml
  6. 16 3
      config/postgresql.conf
  7. 2 2
      deployment/vagrant-common/bootstrap.sh
  8. 3 1
      deployment/vagrant-common/core.rb
  9. 6 6
      deployment/vagrant-production/Vagrantfile
  10. 3 13
      frameworks/C++/ULib/benchmark_config
  11. 8 4
      frameworks/C++/ULib/install.sh
  12. 9 0
      frameworks/C++/ULib/setup.sh
  13. 4 3
      frameworks/C++/ULib/setup_mysql.sh
  14. 4 3
      frameworks/C++/ULib/setup_postgres.sh
  15. 4 3
      frameworks/C++/ULib/setup_sqlite.sh
  16. 32 22
      frameworks/C++/ULib/src/db.usp
  17. 25 15
      frameworks/C++/ULib/src/fortune.usp
  18. 6 1
      frameworks/C++/ULib/src/json.usp
  19. 32 21
      frameworks/C++/ULib/src/query.usp
  20. 43 33
      frameworks/C++/ULib/src/update.usp
  21. 35 67
      frameworks/C++/wt/benchmark.cpp
  22. 1 1
      frameworks/C/haywire/benchmark_config
  23. 74 4
      frameworks/C/lwan/README.md
  24. 19 4
      frameworks/C/lwan/benchmark_config
  25. 1 1
      frameworks/C/lwan/install.sh
  26. 1 1
      frameworks/Go/beego/benchmark_config
  27. 1 1
      frameworks/Groovy/grails/README.md
  28. 0 4
      frameworks/Groovy/grails/bash_profile.sh
  29. 1 1
      frameworks/Groovy/grails/hello/application.properties
  30. 4 4
      frameworks/Groovy/grails/hello/grails-app/conf/BuildConfig.groovy
  31. 3 0
      frameworks/Groovy/grails/hello/grails-app/conf/mysql-connection.properties
  32. 3 6
      frameworks/Groovy/grails/hello/grails-app/controllers/hello/HelloController.groovy
  33. 3 0
      frameworks/Groovy/grails/hello/grails-app/domain/hello/Fortune.groovy
  34. 3 0
      frameworks/Groovy/grails/hello/grails-app/domain/hello/World.groovy
  35. 0 85
      frameworks/Groovy/grails/hello/src/groovy/org/codehaus/groovy/grails/plugins/codecs/JSONEncoder.java
  36. 5 1
      frameworks/Groovy/grails/install.sh
  37. 6 1
      frameworks/Groovy/grails/setup.sh
  38. 18 14
      frameworks/Java/activeweb/benchmark_config
  39. 48 11
      frameworks/Java/activeweb/pom.xml
  40. 14 14
      frameworks/Java/activeweb/source_code
  41. 2 4
      frameworks/Java/activeweb/src/main/java/app/config/AppBootstrap.java
  42. 2 2
      frameworks/Java/activeweb/src/main/java/app/config/AppControllerConfig.java
  43. 0 30
      frameworks/Java/activeweb/src/main/java/app/config/FreeMarkerConfig.java
  44. 1 4
      frameworks/Java/activeweb/src/main/java/app/config/RouteConfig.java
  45. 0 39
      frameworks/Java/activeweb/src/main/java/app/controllers/DatabaseController.java
  46. 40 0
      frameworks/Java/activeweb/src/main/java/app/controllers/DbController.java
  47. 16 19
      frameworks/Java/activeweb/src/main/java/app/controllers/FortunesController.java
  48. 24 33
      frameworks/Java/activeweb/src/main/java/app/controllers/JsonController.java
  49. 15 22
      frameworks/Java/activeweb/src/main/java/app/controllers/PlaintextController.java
  50. 26 32
      frameworks/Java/activeweb/src/main/java/app/controllers/QueriesController.java
  51. 18 21
      frameworks/Java/activeweb/src/main/java/app/controllers/UpdatesController.java
  52. 1 1
      frameworks/Java/activeweb/src/main/java/app/models/Fortune.java
  53. 38 0
      frameworks/Java/activeweb/src/main/java/app/models/Message.java
  54. 19 17
      frameworks/Java/activeweb/src/main/java/app/models/World.java
  55. 1 0
      frameworks/Java/activeweb/src/main/resources/activeweb.properties
  56. 0 20
      frameworks/Java/activeweb/src/main/webapp/WEB-INF/views/fortunes/index.ftl
  57. 1 0
      frameworks/Java/activeweb/src/main/webapp/WEB-INF/views/fortunes/index.html
  58. 0 0
      frameworks/Java/activeweb/src/main/webapp/WEB-INF/views/home/index.html
  59. 1 0
      frameworks/Java/activeweb/src/main/webapp/WEB-INF/views/json/index.html
  60. 10 5
      frameworks/Java/activeweb/src/main/webapp/WEB-INF/views/layouts/default_layout.html
  61. 0 3
      frameworks/Java/activeweb/src/main/webapp/WEB-INF/views/layouts/footer.ftl
  62. 0 4
      frameworks/Java/activeweb/src/main/webapp/WEB-INF/views/layouts/header.ftl
  63. 0 7
      frameworks/Java/activeweb/src/main/webapp/WEB-INF/views/queries/index.ftl
  64. 1 0
      frameworks/Java/activeweb/src/main/webapp/WEB-INF/views/queries/index.html
  65. 0 0
      frameworks/Java/activeweb/src/main/webapp/WEB-INF/views/system/404.html
  66. 0 0
      frameworks/Java/activeweb/src/main/webapp/WEB-INF/views/system/error.html
  67. 0 46
      frameworks/Java/activeweb/src/test/java/app/controllers/DatabaseControllerSpec.java
  68. 66 0
      frameworks/Java/activeweb/src/test/java/app/controllers/DbControllerSpec.java
  69. 48 0
      frameworks/Java/activeweb/src/test/java/app/controllers/FortunesControllerSpec.java
  70. 33 26
      frameworks/Java/activeweb/src/test/java/app/controllers/JsonControllerSpec.java
  71. 42 0
      frameworks/Java/activeweb/src/test/java/app/controllers/PlaintextControllerSpec.java
  72. 3 3
      frameworks/Java/curacao/build.sbt
  73. 2 2
      frameworks/Java/curacao/src/main/java/benchmark/Benchmarks.java
  74. 5 5
      frameworks/Java/gemini/Docroot/WEB-INF/GeminiHello.conf
  75. BIN
      frameworks/Java/gemini/Docroot/WEB-INF/lib/postgresql-9.4-1200.jdbc41.jar
  76. 1 1
      frameworks/Java/gemini/Docroot/WEB-INF/resin.xml
  77. 41 3
      frameworks/Java/gemini/benchmark_config
  78. 1 0
      frameworks/Java/gemini/source_code
  79. 4 2
      frameworks/Java/gemini/start.sh
  80. 9 0
      frameworks/Java/gemini/start_postgres.sh
  81. 3 3
      frameworks/Java/netty/pom.xml
  82. 8 1
      frameworks/Java/netty/src/main/java/hello/HelloWebServer.java
  83. 1 1
      frameworks/Java/ninja-standalone/pom.xml
  84. 8 1
      frameworks/Java/play2-java/setup_java.sh
  85. 8 1
      frameworks/Java/play2-java/setup_java_ebean_bonecp.sh
  86. 8 1
      frameworks/Java/play2-java/setup_java_ebean_hikaricp.sh
  87. 8 1
      frameworks/Java/play2-java/setup_java_jpa_bonecp.sh
  88. 8 1
      frameworks/Java/play2-java/setup_java_jpa_hikaricp.sh
  89. 3 0
      frameworks/Java/sabina/bash_profile.sh
  90. 10 8
      frameworks/Java/sabina/benchmark_config
  91. 3 0
      frameworks/Java/sabina/install.sh
  92. 135 0
      frameworks/Java/sabina/pom.xml
  93. 44 0
      frameworks/Java/sabina/readme.md
  94. 4 0
      frameworks/Java/sabina/setup.sh
  95. 4 0
      frameworks/Java/sabina/source_code
  96. 141 0
      frameworks/Java/sabina/src/main/java/sabina/benchmark/Application.java
  97. 9 0
      frameworks/Java/sabina/src/main/java/sabina/benchmark/Fortune.java
  98. 5 0
      frameworks/Java/sabina/src/main/java/sabina/benchmark/Message.java
  99. 5 0
      frameworks/Java/sabina/src/main/java/sabina/benchmark/World.java
  100. 20 0
      frameworks/Java/sabina/src/main/resources/sabina/view/fortunes.ftl

+ 1 - 2
.travis.yml

@@ -69,6 +69,7 @@ env:
     - "TESTDIR=Java/servlet"
     - "TESTDIR=Java/servlet3-cass"
     - "TESTDIR=Java/spark"
+    - "TESTDIR=Java/sabina"
     - "TESTDIR=Java/spring"
     - "TESTDIR=Java/tapestry"
     - "TESTDIR=Java/undertow"
@@ -106,7 +107,6 @@ env:
     - "TESTDIR=PHP/php-pimf"
     - "TESTDIR=PHP/php-silex"
     - "TESTDIR=PHP/php-silex-orm"
-    - "TESTDIR=PHP/php-silica"
     - "TESTDIR=PHP/php-slim"
     - "TESTDIR=PHP/symfony2"
     - "TESTDIR=PHP/symfony2-stripped"
@@ -136,7 +136,6 @@ env:
     - "TESTDIR=Scala/lift-stateless"
     - "TESTDIR=Scala/plain"
     - "TESTDIR=Scala/play-activate-mysql"
-    - "TESTDIR=Scala/play-scala-mongodb"
     - "TESTDIR=Scala/play2-scala"
     - "TESTDIR=Scala/scalatra"
     - "TESTDIR=Scala/scruffy"

+ 1 - 1
config/benchmark_profile

@@ -20,7 +20,7 @@ export TFB_DISTRIB_DESCRIPTION=$DISTRIB_DESCRIPTION
 
 export JAVA_HOME=/usr/lib/jvm/java-1.7.0-openjdk-amd64
 export RESIN_HOME=${IROOT}/resin-4.0.41
-export GRAILS_HOME=${IROOT}/grails-2.4.2
+export GRAILS_HOME=${IROOT}/grails-2.4.4
 export VERTX_HOME=${IROOT}/vert.x-2.1.1
 export TOMCAT_HOME=${IROOT}/apache-tomcat-7.0.35
 export NODE_HOME=${IROOT}/node-v0.10.8-linux-x64

+ 172 - 0
config/cassandra/cassandra.init

@@ -0,0 +1,172 @@
+#! /bin/sh
+### BEGIN INIT INFO
+# Provides:          cassandra
+# Required-Start:    $remote_fs $network $named $time
+# Required-Stop:     $remote_fs $network $named $time
+# Should-Start:      ntp mdadm
+# Should-Stop:       ntp mdadm
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: distributed storage system for structured data
+# Description:       Cassandra is a distributed (peer-to-peer) system for
+#                    the management and storage of structured data.
+### END INIT INFO
+
+# Author: Eric Evans <[email protected]>
+
+DESC="Cassandra"
+NAME=cassandra
+PIDFILE=/var/run/$NAME/$NAME.pid
+SCRIPTNAME=/etc/init.d/$NAME
+CASSANDRA_CONF=/etc/cassandra
+WAIT_FOR_START=10
+CASSANDRA_HOME=/usr/share/cassandra
+CASSANDRA_LIB=$CASSANDRA_HOME
+CASSANDRA_PROG=/usr/sbin/cassandra
+FD_LIMIT=100000
+
+# Read configuration variable file if it is present
+[ -r /etc/default/$NAME ] && . /etc/default/$NAME
+
+valid_chome=`find $CASSANDRA_LIB/apache-cassandra*.jar 2> /dev/null`
+[ -n "$valid_chome" ] || exit 0
+[ -e $CASSANDRA_CONF/cassandra.yaml ] || exit 0
+[ -e $CASSANDRA_CONF/cassandra-env.sh ] || exit 0
+
+# Read Cassandra environment file.
+. $CASSANDRA_CONF/cassandra-env.sh
+
+if [ -z "$JVM_OPTS" ]; then
+    echo "Initialization failed; \$JVM_OPTS not set!" >&2
+    exit 3
+fi
+
+export JVM_OPTS
+
+# Export JAVA_HOME, if set.
+[ -n "$JAVA_HOME" ] && export JAVA_HOME
+
+# Load the VERBOSE setting and other rcS variables
+. /lib/init/vars.sh
+
+# Define LSB log_* functions.
+# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
+. /lib/lsb/init-functions
+
+#
+# Function that returns 0 if process is running, or nonzero if not.
+#
+# The nonzero value is 3 if the process is simply not running, and 1 if the
+# process is not running but the pidfile exists (to match the exit codes for
+# the "status" command; see LSB core spec 3.1, section 20.2)
+#
+CMD_PATT="cassandra.+CassandraDaemon"
+is_running()
+{
+    if [ -f $PIDFILE ]; then
+        pid=`cat $PIDFILE`
+        grep -Eq "$CMD_PATT" "/proc/$pid/cmdline" 2>/dev/null && return 0
+        return 1
+    fi
+    return 3
+}
+
+#
+# Function that starts the daemon/service
+#
+do_start()
+{
+    # Return
+    #   0 if daemon has been started
+    #   1 if daemon was already running
+    #   2 if daemon could not be started
+
+    ulimit -l unlimited
+    ulimit -n "$FD_LIMIT"
+
+    cassandra_home=`getent passwd cassandra | awk -F ':' '{ print $6; }'`
+    heap_dump_f="$cassandra_home/java_`date +%s`.hprof"
+    error_log_f="$cassandra_home/hs_err_`date +%s`.log"
+
+    [ -e `dirname "$PIDFILE"` ] || \
+        install -d -ocassandra -gcassandra -m755 `dirname $PIDFILE`
+
+
+
+    start-stop-daemon -S -c cassandra -a $CASSANDRA_PROG -q -p "$PIDFILE" -t >/dev/null || return 1
+
+    start-stop-daemon -S -c cassandra -a $CASSANDRA_PROG -b -p "$PIDFILE" -- \
+        -p "$PIDFILE" -H "$heap_dump_f" -E "$error_log_f" >/dev/null || return 2
+
+}
+
+#
+# Function that stops the daemon/service
+#
+do_stop()
+{
+    # Return
+    #   0 if daemon has been stopped
+    #   1 if daemon was already stopped
+    #   2 if daemon could not be stopped
+    #   other if a failure occurred
+    start-stop-daemon -K -p "$PIDFILE" -R TERM/30/KILL/5 >/dev/null
+    RET=$?
+    rm -f "$PIDFILE"
+    return $RET
+}
+
+case "$1" in
+  start)
+	[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
+	do_start
+	case "$?" in
+		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+	esac
+	;;
+  stop)
+	[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
+	do_stop
+	case "$?" in
+		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+	esac
+	;;
+  restart|force-reload)
+	log_daemon_msg "Restarting $DESC" "$NAME"
+	do_stop
+	case "$?" in
+	  0|1)
+		do_start
+		case "$?" in
+			0) log_end_msg 0 ;;
+			1) log_end_msg 1 ;; # Old process is still running
+			*) log_end_msg 1 ;; # Failed to start
+		esac
+		;;
+	  *)
+	  	# Failed to stop
+		log_end_msg 1
+		;;
+	esac
+	;;
+  status)
+    is_running
+    stat=$?
+    case "$stat" in
+      0) log_success_msg "$DESC is running" ;;
+      1) log_failure_msg "could not access pidfile for $DESC" ;;
+      *) log_success_msg "$DESC is not running" ;;
+    esac
+    exit "$stat"
+    ;;
+  *)
+	echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload|status}" >&2
+	exit 3
+	;;
+esac
+
+:
+
+# vi:ai sw=4 ts=4 tw=0 et

+ 6 - 0
config/cassandra/cassandra.init.env

@@ -0,0 +1,6 @@
+
+CASSANDRA_HOME=/opt/cassandra
+CASSANDRA_LIB=$CASSANDRA_HOME/lib
+CASSANDRA_CONF=$CASSANDRA_HOME/conf
+CASSANDRA_PROG=$CASSANDRA_HOME/bin/cassandra
+

+ 37 - 14
config/cassandra/cassandra.yaml

@@ -7,7 +7,7 @@
 
 # The name of the cluster. This is mainly used to prevent machines in
 # one logical cluster from joining another.
-cluster_name: 'Benchmark Cluster'
+cluster_name: 'TFB Cluster'
 
 # This defines the number of tokens randomly assigned to this node on the ring
 # The more tokens, relative to other nodes, the larger the proportion of data
@@ -17,7 +17,8 @@ cluster_name: 'Benchmark Cluster'
 # If you leave this unspecified, Cassandra will use the default of 1 token for legacy compatibility,
 # and will use the initial_token as described below.
 #
-# Specifying initial_token will override this setting.
+# Specifying initial_token will override this setting on the node's initial start,
+# on subsequent starts, this setting will apply even if initial token is set.
 #
 # If you already have a cluster with 1 token per node, and wish to migrate to 
 # multiple tokens per node, see http://wiki.apache.org/cassandra/Operations
@@ -78,6 +79,14 @@ authorizer: AllowAllAuthorizer
 # Will be disabled automatically for AllowAllAuthorizer.
 permissions_validity_in_ms: 2000
 
+# Refresh interval for permissions cache (if enabled).
+# After this interval, cache entries become eligible for refresh. Upon next
+# access, an async reload is scheduled and the old value returned until it
+# completes. If permissions_validity_in_ms is non-zero, then this must be
+# also.
+# Defaults to the same value as permissions_validity_in_ms.
+# permissions_update_interval_in_ms: 1000
+
 # The partitioner is responsible for distributing groups of rows (by
 # partition key) across nodes in the cluster.  You should leave this
 # alone for new clusters.  The partitioner can NOT be changed without
@@ -224,7 +233,7 @@ seed_provider:
       parameters:
           # seeds is actually a comma-delimited list of addresses.
           # Ex: "<ip1>,<ip2>,<ip3>"
-          - seeds: "TFB_DATABASE_HOST"
+          - seeds: "127.0.0.1"
 
 # For workloads with more data than can fit in memory, Cassandra's
 # bottleneck will be reads that need to fetch data from
@@ -294,7 +303,7 @@ ssl_storage_port: 7001
 # address associated with the hostname (it might not be).
 #
 # Setting this to 0.0.0.0 is always wrong.
-listen_address: TFB_DATABASE_HOST
+listen_address: 127.0.0.1
 
 # Address to broadcast to other Cassandra nodes
 # Leaving this blank will set it to the same value as listen_address
@@ -332,11 +341,11 @@ start_rpc: true
 # Note that unlike ListenAddress above, it is allowed to specify 0.0.0.0
 # here if you want to listen on all interfaces, but that will break clients 
 # that rely on node auto-discovery.
-rpc_address: TFB_DATABASE_HOST
+rpc_address: 127.0.0.1
 # port for Thrift to listen for clients on
 rpc_port: 9160
 
-# enable or disable keepalive on rpc connections
+# enable or disable keepalive on rpc/native connections
 rpc_keepalive: true
 
 # Cassandra provides two out-of-the-box options for the RPC Server:
@@ -349,7 +358,8 @@ rpc_keepalive: true
 # hsha  -> Stands for "half synchronous, half asynchronous." All thrift clients are handled
 #          asynchronously using a small number of threads that does not vary with the amount
 #          of thrift clients (and thus scales well to many clients). The rpc requests are still
-#          synchronous (one thread per active request).
+#          synchronous (one thread per active request). If hsha is selected then it is essential
+#          that rpc_max_threads is changed from the default value of unlimited.
 #
 # The default is sync because on Windows hsha is about 30% slower.  On Linux,
 # sync/hsha performance is about the same, with hsha of course using less memory.
@@ -420,15 +430,22 @@ auto_snapshot: true
 tombstone_warn_threshold: 1000
 tombstone_failure_threshold: 100000
 
-# Add column indexes to a row after its contents reach this size.
-# Increase if your column values are large, or if you have a very large
-# number of columns.  The competing causes are, Cassandra has to
-# deserialize this much of the row to read a single column, so you want
-# it to be small - at least if you do many partial-row reads - but all
-# the index data is read for each access, so you don't want to generate
-# that wastefully either.
+# Granularity of the collation index of rows within a partition.
+# Increase if your rows are large, or if you have a very large
+# number of rows per partition.  The competing goals are these:
+#   1) a smaller granularity means more index entries are generated
+#      and looking up rows withing the partition by collation column
+#      is faster
+#   2) but, Cassandra will keep the collation index in memory for hot
+#      rows (as part of the key cache), so a larger granularity means
+#      you can cache more hot rows
 column_index_size_in_kb: 64
 
+
+# Log WARN on any batch size exceeding this value. 5kb per batch by default.
+# Caution should be taken on increasing the size of this threshold as it can lead to node instability.
+batch_size_warn_threshold_in_kb: 5
+
 # Size limit for rows being compacted in memory.  Larger rows will spill
 # over to disk and use a slower two-pass compaction process.  A message
 # will be logged specifying the row key.
@@ -474,6 +491,12 @@ compaction_preheat_key_cache: true
 # When unset, the default is 200 Mbps or 25 MB/s.
 # stream_throughput_outbound_megabits_per_sec: 200
 
+# Throttles all streaming file transfer between the datacenters,
+# this setting allows users to throttle inter dc stream throughput in addition
+# to throttling all network stream traffic as configured with
+# stream_throughput_outbound_megabits_per_sec
+# inter_dc_stream_throughput_outbound_megabits_per_sec:
+
 # How long the coordinator should wait for read operations to complete
 read_request_timeout_in_ms: 5000
 # How long the coordinator should wait for seq or index scans to complete

+ 16 - 3
config/postgresql.conf

@@ -61,7 +61,7 @@ listen_addresses = '*'		# what IP address(es) to listen on;
 					# defaults to 'localhost', '*' = all
 					# (change requires restart)
 port = 5432				# (change requires restart)
-max_connections = 2000			# (change requires restart)
+max_connections = 5000			# (change requires restart)
 # Note:  Increasing max_connections costs ~400 bytes of shared memory per
 # connection slot, plus lock space (see max_locks_per_transaction).
 #superuser_reserved_connections = 3	# (change requires restart)
@@ -105,8 +105,21 @@ ssl = false                             # (change requires restart)
 #------------------------------------------------------------------------------
 
 # - Memory -
-
-shared_buffers = 32MB			# min 128kB
+# values from: http://blog.pgaddict.com/posts/performance-since-postgresql-7-4-to-9-4-pgbench
+# details: http://www.postgresql.org/docs/9.4/static/runtime-config-resource.html
+# http://www.postgresql.org/docs/9.4/static/runtime-config-wal.html
+# http://www.postgresql.org/docs/9.4/static/runtime-config-query.html
+shared_buffers = 2GB                    # min 128kB
+work_mem = 64MB                                # min 64kB
+maintenance_work_mem = 512MB            # min 1MB
+checkpoint_segments = 64
+checkpoint_completion_target = 0.9
+effective_cache_size = 8GB
+
+# when executed on the SSD (otherwise 4)
+random_page_cost = 2
+
+#shared_buffers = 32MB			# min 128kB
 					# (change requires restart)
 #temp_buffers = 8MB			# min 800kB
 #max_prepared_transactions = 0		# zero disables the feature

+ 2 - 2
deployment/vagrant-common/bootstrap.sh

@@ -75,8 +75,8 @@ if [ ! -e "~/.firstboot" ]; then
   echo $CLIENT_IP TFB-client   | sudo tee --append /etc/hosts
   echo $SERVER_IP TFB-server   | sudo tee --append /etc/hosts
 
-  # Add other users:
-  sudo useradd -m testrunner
+  # Add user to run tests
+  sudo adduser --disabled-password --gecos "" testrunner
   # WARN: testrunner will NOT have sudo access by round 11
   #       please begin migrating scripts to not rely on sudo.
   sudo bash -c "echo 'testrunner ALL=(ALL) NOPASSWD:ALL' > /etc/sudoers.d/90-tfb-testrunner"

+ 3 - 1
deployment/vagrant-common/core.rb

@@ -77,7 +77,9 @@ def provider_aws(config, role, ip_address='172.16.0.16')
   end
 end
 
-def provider_virtualbox(config, role)
+def provider_virtualbox(config, role, ip_address='172.16.0.16')
+  config.vm.network "private_network", ip: ip_address
+  
   config.vm.provider :virtualbox do |vb, override|
     override.vm.hostname = "TFB-#{role}"
 

+ 6 - 6
deployment/vagrant-production/Vagrantfile

@@ -8,9 +8,9 @@ check_provider_needs(provider)
 
 Vagrant.configure("2") do |config|
 
-  server_ip = ENV.fetch('TFB_AWS_LOAD_IP', '172.16.0.16')
-  client_ip = ENV.fetch('TFB_AWS_DB_IP', '172.16.0.17')
-  databa_ip = ENV.fetch('TFB_AWS_APP_IP', '172.16.0.18')
+  server_ip = ENV.fetch('TFB_AWS_APP_IP', '172.16.0.16')
+  client_ip = ENV.fetch('TFB_AWS_LOAD_IP', '172.16.0.17')
+  databa_ip = ENV.fetch('TFB_AWS_DB_IP', '172.16.0.18')
   
   # Put the keys inside each box
   Dir['keys/*'].each do |fname|
@@ -28,20 +28,20 @@ Vagrant.configure("2") do |config|
   config.vm.define "client" do |client|
     provision_bootstrap(client, "client")
     provider_aws(client, "loadgen", client_ip)
-    provider_virtualbox(client, "client")
+    provider_virtualbox(client, "client", client_ip)
   end
 
   config.vm.define "db" do |db|
     provision_bootstrap(db, "database")
     provider_aws(db, "database", databa_ip)
-    provider_virtualbox(db, "database")
+    provider_virtualbox(db, "database", databa_ip)
   end
 
   # Define the app server as the primary VM
   config.vm.define "app", primary: true do |app|
     provision_bootstrap(app, "server")
     provider_aws(app, "appserver", server_ip)
-    provider_virtualbox(app, "server")
+    provider_virtualbox(app, "server", server_ip)
   end
 
 end

+ 3 - 13
frameworks/C++/ULib/benchmark_config

@@ -2,17 +2,13 @@
   "framework": "ULib",
   "tests": [{
     "default": {
-      "setup_file": "setup_mysql",
+      "setup_file": "setup",
       "json_url": "/json",
-      "db_url": "/db",
-      "query_url": "/query?queries=",
-      "fortune_url": "/fortune",
-      "update_url": "/update?queries=",
       "plaintext_url": "/plaintext",
       "port": 8080,
       "approach": "Realistic",
       "classification": "Platform",
-      "database": "MySQL",
+      "database": "None",
       "framework": "ULib",
       "language": "C++",
       "orm": "Micro",
@@ -20,18 +16,16 @@
       "webserver": "userver_tcp",
       "os": "Linux",
       "database_os": "Linux",
-      "display_name": "ULib-mysql",
+      "display_name": "ULib",
       "notes": "",
       "versus": ""
     },
     "mysql": {
       "setup_file": "setup_mysql",
-      "json_url": "/json",
       "db_url": "/db",
       "query_url": "/query?queries=",
       "fortune_url": "/fortune",
       "update_url": "/update?queries=",
-      "plaintext_url": "/plaintext",
       "port": 8080,
       "approach": "Realistic",
       "classification": "Platform",
@@ -49,11 +43,9 @@
     },
     "sqlite": {
       "setup_file": "setup_sqlite",
-      "json_url": "/json",
       "db_url": "/db",
       "query_url": "/query?queries=",
       "fortune_url": "/fortune",
-      "plaintext_url": "/plaintext",
       "port": 8080,
       "approach": "Realistic",
       "classification": "Platform",
@@ -71,12 +63,10 @@
     },
     "postgres": {
       "setup_file": "setup_postgres",
-      "json_url": "/json",
       "db_url": "/db",
       "query_url": "/query?queries=",
       "fortune_url": "/fortune",
       "update_url": "/update?queries=",
-      "plaintext_url": "/plaintext",
       "port": 8080,
       "approach": "Realistic",
       "classification": "Platform",

+ 8 - 4
frameworks/C++/ULib/install.sh

@@ -16,6 +16,10 @@
 #    . $FWROOT/ULib/install.sh (cwd=$FWROOT//installs)
 # --------------------------------------------------------------------------------------------------------
 
+ULIB_VERSION=1.4.2
+ULIB_ROOT=$IROOT/ULib
+ULIB_DOCUMENT_ROOT=${ULIB_ROOT}/ULIB_DOCUMENT_ROOT
+
 # Check if ULib is already installed
 ULIB_INSTALLED_FILE="${IROOT}/ULib-${ULIB_VERSION}.installed"
 RETCODE=$(fw_exists ${ULIB_INSTALLED_FILE})
@@ -37,12 +41,12 @@ if [ ! -f "benchmark.cfg" ]; then
   cat <<EOF >benchmark.cfg
 userver {
  PORT 8080
- PREFORK_CHILD 8
- LISTEN_BACKLOG 8192
- MAX_KEEP_ALIVE 8192
+ PREFORK_CHILD 4
+ MAX_KEEP_ALIVE 1023
+ LISTEN_BACKLOG 16384
+ CLIENT_FOR_PARALLELIZATION 256
  ORM_DRIVER "mysql pgsql sqlite"
  DOCUMENT_ROOT $ULIB_DOCUMENT_ROOT
-#PID_FILE ${ULIB_ROOT}/userver_tcp.pid
 }
 EOF
 fi

+ 9 - 0
frameworks/C++/ULib/setup.sh

@@ -0,0 +1,9 @@
+#!/bin/bash
+
+export UMEMPOOL="176,100,0,37,1160,155,-17,-22,40"
+
+# 1. Change ULib Server configuration
+sed -i "s|PREFORK_CHILD .*|PREFORK_CHILD ${MAX_THREADS}|g" ${IROOT}/ULib/benchmark.cfg
+
+# 2. Start ULib Server (userver_tcp)
+${IROOT}/ULib/bin/userver_tcp -c ${IROOT}/ULib/benchmark.cfg &

+ 4 - 3
frameworks/C++/ULib/setup_mysql.sh

@@ -1,11 +1,12 @@
 #!/bin/bash
 
-export UMEMPOOL="545,0,0,37,8465,0,-17,-22,34"
 export ORM_DRIVER="mysql"
 export ORM_OPTION="host=${DBHOST} user=benchmarkdbuser password=benchmarkdbpass character-set=utf8 dbname=hello_world"
 
+export UMEMPOOL="176,100,0,37,1160,155,-17,-22,40"
+
 # 1. Change ULib Server configuration
-sed -i "s|PREFORK_CHILD .*|PREFORK_CHILD ${MAX_THREADS}|g" $ULIB_ROOT/benchmark.cfg
+sed -i "s|PREFORK_CHILD .*|PREFORK_CHILD ${MAX_THREADS}|g" $IROOT/ULib/benchmark.cfg
 
 # 2. Start ULib Server (userver_tcp)
-$ULIB_ROOT/bin/userver_tcp -c $ULIB_ROOT/benchmark.cfg &
+$IROOT/ULib/bin/userver_tcp -c $IROOT/ULib/benchmark.cfg &

+ 4 - 3
frameworks/C++/ULib/setup_postgres.sh

@@ -1,11 +1,12 @@
 #!/bin/bash
 
-export UMEMPOOL="545,0,0,37,8465,0,-17,-22,34"
 export ORM_DRIVER="pgsql"
 export ORM_OPTION="host=${DBHOST} user=benchmarkdbuser password=benchmarkdbpass dbname=hello_world client_encoding=UTF8"
 
+export UMEMPOOL="176,100,0,37,1160,155,-17,-22,40"
+
 # 1. Change ULib Server configuration
-sed -i "s|PREFORK_CHILD .*|PREFORK_CHILD ${MAX_THREADS}|g" $ULIB_ROOT/benchmark.cfg
+sed -i "s|PREFORK_CHILD .*|PREFORK_CHILD ${MAX_THREADS}|g" $IROOT/ULib/benchmark.cfg
 
 # 2. Start ULib Server (userver_tcp)
-$ULIB_ROOT/bin/userver_tcp -c $ULIB_ROOT/benchmark.cfg &
+$IROOT/ULib/bin/userver_tcp -c $IROOT/ULib/benchmark.cfg &

+ 4 - 3
frameworks/C++/ULib/setup_sqlite.sh

@@ -1,11 +1,12 @@
 #!/bin/bash
 
-export UMEMPOOL="545,0,0,37,8465,0,-17,-22,34"
 export ORM_DRIVER="sqlite"
 export ORM_OPTION="host=${DBHOST} user=benchmarkdbuser password=benchmarkdbpass character-set=utf8 dbname=${ULIB_ROOT}/db/%.*s"
 
+export UMEMPOOL="176,100,0,37,1160,155,-17,-22,40"
+
 # 1. Change ULib Server configuration
-sed -i "s|PREFORK_CHILD .*|PREFORK_CHILD ${MAX_THREADS}|g" $ULIB_ROOT/benchmark.cfg
+sed -i "s|PREFORK_CHILD .*|PREFORK_CHILD ${MAX_THREADS}|g" ${IROOT}/ULib/benchmark.cfg
 
 # 2. Start ULib Server (userver_tcp)
-$ULIB_ROOT/bin/userver_tcp -c $ULIB_ROOT/benchmark.cfg &
+${IROOT}/ULib/bin/userver_tcp -c ${IROOT}/ULib/benchmark.cfg &

+ 32 - 22
frameworks/C++/ULib/src/db.usp

@@ -1,48 +1,58 @@
+<!--#
+Test type 2: Single database query
+TechEmpower Web Framework Benchmarks
+-->
 <!--#declaration
 #include "world.h"
 
-#ifndef AS_cpoll_cppsp_DO
-static UValue* pvalue;
-#endif
 static World*         pworld_db;
 static UOrmSession*   psql_db;
 static UOrmStatement* pstmt_db;
 
-static void usp_init_db()
-{
-   U_TRACE(5, "::usp_init_db()")
-
-   pworld_db = U_NEW(World);
-
 #ifndef AS_cpoll_cppsp_DO
-   pvalue = U_NEW(UValue(OBJECT_VALUE));
+static UValue* pvalue;
 #endif
-}
 
 static void usp_fork_db()
 {
    U_TRACE(5, "::usp_fork_db()")
 
-   psql_db  = U_NEW(UOrmSession(U_CONSTANT_TO_PARAM("hello_world")));
-   pstmt_db = U_NEW(UOrmStatement(*psql_db, U_CONSTANT_TO_PARAM("SELECT randomNumber FROM World WHERE id = ?")));
+   psql_db = U_NEW(UOrmSession(U_CONSTANT_TO_PARAM("hello_world")));
+
+   if (psql_db->isReady())
+      {
+      pstmt_db = U_NEW(UOrmStatement(*psql_db, U_CONSTANT_TO_PARAM("SELECT randomNumber FROM World WHERE id = ?")));
+
+      if (pstmt_db == 0) U_ERROR("usp_fork_db(): we cound't connect to db");
+
+      pworld_db = U_NEW(World);
 
-   if (pstmt_db == 0) U_ERROR("usp_fork_db(): we cound't connect to db");
+      pstmt_db->use( pworld_db->id);
+      pstmt_db->into(pworld_db->randomNumber);
 
-   pstmt_db->use( pworld_db->id);
-   pstmt_db->into(pworld_db->randomNumber);
+#  ifndef AS_cpoll_cppsp_DO
+      pvalue = U_NEW(UValue(OBJECT_VALUE));
+#  endif
+      }
 }
 
+#ifdef DEBUG
 static void usp_end_db()
 {
    U_TRACE(5, "::usp_end_db()")
 
-   delete pstmt_db;
-   delete psql_db;
-   delete pworld_db;
-#ifndef AS_cpoll_cppsp_DO
-   delete pvalue;
-#endif
+   if (pstmt_db)
+      {
+      delete  pstmt_db;
+      delete   psql_db;
+      delete pworld_db;
+
+#  ifndef AS_cpoll_cppsp_DO
+      delete pvalue;
+#  endif
+      }
 }
+#endif
 -->
 <!--#header
 Content-Type: application/json; charset=UTF-8

+ 25 - 15
frameworks/C++/ULib/src/fortune.usp

@@ -1,43 +1,53 @@
+<!--#
+Test type 4: Fortunes
+TechEmpower Web Framework Benchmarks
+-->
 <!--#declaration
 #include "fortune.h"
 
-static UOrmSession*       psql_fortune;
-static UOrmStatement*     pstmt_fortune;
 static Fortune*           pfortune;
 static UString*           pmessage;
+static UOrmSession*       psql_fortune;
+static UOrmStatement*     pstmt_fortune;
 static UVector<Fortune*>* pvfortune;
 
-static void usp_init_fortune()
-{
-   U_TRACE(5, "::usp_init_fortune()")
-
-   pfortune  = U_NEW(Fortune);
-   pvfortune = U_NEW(UVector<Fortune*>);
-   pmessage  = U_NEW(U_STRING_FROM_CONSTANT("Additional fortune added at request time."));
-}
-
 static void usp_fork_fortune()
 {
    U_TRACE(5, "::usp_fork_fortune()")
 
-   psql_fortune  = U_NEW(UOrmSession(U_CONSTANT_TO_PARAM("fortune")));
-   pstmt_fortune = U_NEW(UOrmStatement(*psql_fortune, U_CONSTANT_TO_PARAM("SELECT id, message FROM Fortune")));
+   psql_fortune = U_NEW(UOrmSession(U_CONSTANT_TO_PARAM("fortune")));
+
+   if (psql_fortune->isReady())
+      {
+      pstmt_fortune = U_NEW(UOrmStatement(*psql_fortune, U_CONSTANT_TO_PARAM("SELECT id, message FROM Fortune")));
+
+      if (pstmt_fortune == 0) U_ERROR("usp_fork_fortune(): we cound't connect to db");
+
+      pfortune = U_NEW(Fortune);
 
-   if (pstmt_fortune == 0) U_ERROR("usp_fork_fortune(): we cound't connect to db");
+      pstmt_fortune->into(*pfortune);
 
-   pstmt_fortune->into(*pfortune);
+      pmessage  = U_NEW(U_STRING_FROM_CONSTANT("Additional fortune added at request time."));
+      pvfortune = U_NEW(UVector<Fortune*>);
+      }
 }
 
+#ifdef DEBUG
 static void usp_end_fortune()
 {
    U_TRACE(5, "::usp_end_fortune()")
 
+   if (pstmt_fortune)
+   {
    delete pstmt_fortune;
+
    delete psql_fortune;
    delete pvfortune;
    delete pfortune;
    delete pmessage;
+   }
 }
+#endif
 -->
 <!doctype html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr><!--#code
 Fortune* elem;

+ 6 - 1
frameworks/C++/ULib/src/json.usp

@@ -1,3 +1,7 @@
+<!--#
+Test type 1: JSON serialization
+TechEmpower Web Framework Benchmarks
+-->
 <!--#declaration
 #ifdef AS_cpoll_cppsp_DO
 #undef AS_cpoll_cppsp_DO
@@ -19,6 +23,7 @@ static void usp_init_json()
 #endif
 }
 
+#ifdef DEBUG
 static void usp_end_json()
 {
    U_TRACE(5, "::usp_end_json()")
@@ -28,6 +33,7 @@ static void usp_end_json()
    delete pvalue;
 #endif
 }
+#endif
 -->
 <!--#header
 Content-Type: application/json; charset=UTF-8
@@ -43,5 +49,4 @@ const char* hello_str = json_object_to_json_string(hello);
 USP_PUTS_STRING(hello_str);
 json_object_put(hello);
 #endif
-U_ClientImage_request_nocache = true;
 -->

+ 32 - 21
frameworks/C++/ULib/src/query.usp

@@ -1,51 +1,62 @@
+<!--#
+Test type 3: Multiple database queries
+TechEmpower Web Framework Benchmarks
+-->
 <!--#declaration
 #include "world.h"
 
-#ifndef AS_cpoll_cppsp_DO
-static UValue* pvalue;
-#endif
+static World*           pworld_query;
 static UOrmSession*     psql_query;
 static UOrmStatement*   pstmt_query;
-static World*           pworld_query;
 static UVector<World*>* pvworld_query;
 
-static void usp_init_query()
-{
-   U_TRACE(5, "::usp_init_query()")
-
-   pworld_query  = U_NEW(World);
-   pvworld_query = U_NEW(UVector<World*>(500));
-
 #ifndef AS_cpoll_cppsp_DO
-   pvalue = U_NEW(UValue(ARRAY_VALUE));
+static UValue* pvalue;
 #endif
-}
 
 static void usp_fork_query()
 {
    U_TRACE(5, "::usp_fork_query()")
 
-   psql_query  = U_NEW(UOrmSession(U_CONSTANT_TO_PARAM("hello_world")));
-   pstmt_query = U_NEW(UOrmStatement(*psql_query, U_CONSTANT_TO_PARAM("SELECT randomNumber FROM World WHERE id = ?")));
+   psql_query = U_NEW(UOrmSession(U_CONSTANT_TO_PARAM("hello_world")));
+
+   if (psql_query->isReady())
+      {
+      pstmt_query = U_NEW(UOrmStatement(*psql_query, U_CONSTANT_TO_PARAM("SELECT randomNumber FROM World WHERE id = ?")));
+
+      if (pstmt_query == 0) U_ERROR("usp_fork_query(): we cound't connect to db");
+
+      pworld_query = U_NEW(World);
+
+      pstmt_query->use( pworld_query->id);
+      pstmt_query->into(pworld_query->randomNumber);
 
-   if (pstmt_query == 0) U_ERROR("usp_fork_query(): we cound't connect to db");
+      pvworld_query = U_NEW(UVector<World*>(500));
 
-   pstmt_query->use( pworld_query->id);
-   pstmt_query->into(pworld_query->randomNumber);
+#  ifndef AS_cpoll_cppsp_DO
+      pvalue = U_NEW(UValue(ARRAY_VALUE));
+#  endif
+      }
 }
 
+#ifdef DEBUG
 static void usp_end_query()
 {
    U_TRACE(5, "::usp_end_query()")
 
-   delete pstmt_query;
-   delete psql_query;
+   if (pstmt_query)
+   {
+   delete   pstmt_query;
+   delete    psql_query;
    delete pvworld_query;
-   delete pworld_query;
+   delete  pworld_query;
+
 #ifndef AS_cpoll_cppsp_DO
    delete pvalue;
 #endif
+   }
 }
+#endif
 -->
 <!--#args
 queries;

+ 43 - 33
frameworks/C++/ULib/src/update.usp

@@ -1,26 +1,19 @@
+<!--#
+Test type 5: Database updates
+TechEmpower Web Framework Benchmarks
+-->
 <!--#declaration
 #include "world.h"
 
-#ifndef AS_cpoll_cppsp_DO
-static UValue* pvalue;
-#endif
+static World*           pworld_update;
 static UOrmSession*     psql_update;
 static UOrmStatement*   pstmt1;
 static UOrmStatement*   pstmt2;
-static World*           pworld_update;
 static UVector<World*>* pvworld_update;
 
-static void usp_init_update()
-{
-   U_TRACE(5, "::usp_init_update()")
-
-   pworld_update  = U_NEW(World);
-   pvworld_update = U_NEW(UVector<World*>(500));
-
 #ifndef AS_cpoll_cppsp_DO
-   pvalue = U_NEW(UValue(ARRAY_VALUE));
+static UValue* pvalue;
 #endif
-}
 
 static void usp_fork_update()
 {
@@ -28,33 +21,52 @@ static void usp_fork_update()
 
    psql_update = U_NEW(UOrmSession(U_CONSTANT_TO_PARAM("hello_world")));
 
-   pstmt1 = U_NEW(UOrmStatement(*psql_update, U_CONSTANT_TO_PARAM("SELECT randomNumber FROM World WHERE id = ?")));
-   pstmt2 = U_NEW(UOrmStatement(*psql_update, U_CONSTANT_TO_PARAM("UPDATE World SET randomNumber = ? WHERE id = ?")));
-
-   if (pstmt1 == 0 ||
-       pstmt2 == 0)
+   if (psql_update->isReady())
       {
-      U_ERROR("usp_fork_update(): we cound't connect to db");
-      }
+      pstmt1 = U_NEW(UOrmStatement(*psql_update, U_CONSTANT_TO_PARAM("SELECT randomNumber FROM World WHERE id = ?")));
+      pstmt2 = U_NEW(UOrmStatement(*psql_update, U_CONSTANT_TO_PARAM("UPDATE World SET randomNumber = ? WHERE id = ?")));
 
-   pstmt1->use( pworld_update->id);
-   pstmt1->into(pworld_update->randomNumber);
-   pstmt2->use( pworld_update->randomNumber, pworld_update->id);
+      if (pstmt1 == 0 ||
+          pstmt2 == 0)
+         {
+         U_ERROR("usp_fork_update(): we cound't connect to db");
+         }
+
+      pworld_update = U_NEW(World);
+
+      pstmt1->use( pworld_update->id);
+      pstmt1->into(pworld_update->randomNumber);
+      pstmt2->use( pworld_update->randomNumber, pworld_update->id);
+
+      pvworld_update = U_NEW(UVector<World*>(500));
+
+#  ifndef AS_cpoll_cppsp_DO
+      pvalue = U_NEW(UValue(ARRAY_VALUE));
+#  endif
+      }
 }
 
+#ifdef DEBUG
 static void usp_end_update()
 {
    U_TRACE(5, "::usp_end_update()")
 
-   delete pstmt1;
-   delete pstmt2;
-   delete psql_update;
-   delete pvworld_update;
-   delete pworld_update;
-#ifndef AS_cpoll_cppsp_DO
-   delete pvalue;
-#endif
+   if (pstmt1 &&
+       pstmt2)
+      {
+      delete pstmt1;
+      delete pstmt2;
+
+      delete    psql_update;
+      delete pvworld_update;
+      delete  pworld_update;
+
+#  ifndef AS_cpoll_cppsp_DO
+      delete pvalue;
+#  endif
+      }
 }
+#endif
 -->
 <!--#args
 queries;
@@ -78,8 +90,6 @@ while (true)
 
    pstmt1->execute();
 
-   U_INTERNAL_DUMP("pworld_update->randomNumber = %u", pworld_update->randomNumber)
-
    pworld_update->randomNumber = u_get_num_random(10000);
 
    pstmt2->execute();

+ 35 - 67
frameworks/C++/wt/benchmark.cpp

@@ -91,57 +91,38 @@ public:
     }
 };
 
-std::mutex mtx;
-
-struct DbStruct {
-#ifndef BENCHMARK_USE_POSTGRES
-  Wt::Dbo::backend::MySQL connection;
+class MyConnection : public
+#ifdef BENCHMARK_USE_POSTGRES
+  Wt::Dbo::backend::Postgres
 #else
-  Wt::Dbo::backend::Postgres connection;
+  Wt::Dbo::backend::MySQL
 #endif
-  Wt::Dbo::Session session;
-  Wt::Dbo::Transaction *transaction;
-
-  boost::taus88 rng;
-  boost::random::uniform_int_distribution<int> distribution;
-
-#ifndef BENCHMARK_USE_POSTGRES
-  DbStruct() : connection("hello_world", "benchmarkdbuser", "benchmarkdbpass", "INSERT_DB_HOST_HERE", 3306),
+{
+public:
+#ifdef BENCHMARK_USE_POSTGRES
+  MyConnection(const std::string &db) :
+  Wt::Dbo::backend::Postgres(db) {}
 #else
-  DbStruct() : connection("host=INSERT_DB_HOST_HERE port=5432 user=benchmarkdbuser password=benchmarkdbpass dbname=hello_world"),
+  MyConnection(const std::string &db, const std::string &dbuser, const std::string &dbpasswd, const std::string &dbhost, unsigned int dbport) :
+  Wt::Dbo::backend::MySQL(db, dbuser, dbpasswd, dbhost, dbport) {}
 #endif
-      rng(clock()),
-      distribution(1, 10000) {
-    session.setConnection(connection);
-    session.mapClass<World>("world");
-    session.mapClass<Fortune>("fortune");
-    transaction = new Wt::Dbo::Transaction(session);
-  }
-
-  ~DbStruct() {
-    delete transaction;
-  }
 
-  int rand() {
-    return distribution(rng);
-  }
+  virtual void startTransaction() { }
+  virtual void commitTransaction() { }
+  virtual void rollbackTransaction() { }
 };
 
-struct DbStructNoTransaction {
-#ifndef BENCHMARK_USE_POSTGRES
-  Wt::Dbo::backend::MySQL connection;
-#else
-  Wt::Dbo::backend::Postgres connection;
-#endif
+struct DbStruct {
+  MyConnection connection;
   Wt::Dbo::Session session;
 
   boost::taus88 rng;
   boost::random::uniform_int_distribution<int> distribution;
 
 #ifndef BENCHMARK_USE_POSTGRES
-  DbStructNoTransaction() : connection("hello_world", "benchmarkdbuser", "benchmarkdbpass", "INSERT_DB_HOST_HERE", 3306),
+  DbStruct() : connection("hello_world", "benchmarkdbuser", "benchmarkdbpass", "INSERT_DB_HOST_HERE", 3306),
 #else
-  DbStructNoTransaction() : connection("host=INSERT_DB_HOST_HERE port=5432 user=benchmarkdbuser password=benchmarkdbpass dbname=hello_world"),
+  DbStruct() : connection("host=INSERT_DB_HOST_HERE port=5432 user=benchmarkdbuser password=benchmarkdbpass dbname=hello_world"),
 #endif
       rng(clock()),
       distribution(1, 10000) {
@@ -155,9 +136,11 @@ struct DbStructNoTransaction {
   }
 };
 
-class DbResource : public Wt::WResource {
-private:
+namespace {
   boost::thread_specific_ptr<DbStruct> dbStruct_;
+}
+
+class DbResource : public Wt::WResource {
 public:
   virtual void handleRequest(const Wt::Http::Request &request, Wt::Http::Response &response) {
     response.setMimeType("application/json");
@@ -165,13 +148,11 @@ public:
 
     DbStruct* db = dbStruct_.get();
     if (!db) {
-      std::lock_guard<std::mutex> lock(mtx);
-      if (!db) {
-        db = new DbStruct();
-        dbStruct_.reset(db);
-      }
+      db = new DbStruct();
+      dbStruct_.reset(db);
     }
 
+    Wt::Dbo::Transaction transaction(db->session);
     Wt::Dbo::ptr<World> entry = db->session.load<World>(db->rand());
     
     Wt::Dbo::JsonSerializer writer(response.out());
@@ -180,8 +161,6 @@ public:
 };
 
 class QueriesResource : public Wt::WResource {
-private:
-  boost::thread_specific_ptr<DbStruct> dbStruct_;
 public:
   virtual void handleRequest(const Wt::Http::Request &request, Wt::Http::Response &response) {
     int n;
@@ -200,13 +179,11 @@ public:
 
     DbStruct* db = dbStruct_.get();
     if (!db) {
-      std::lock_guard<std::mutex> lock(mtx);
-      if (!db) {
-        db = new DbStruct();
-        dbStruct_.reset(db);
-      }
+      db = new DbStruct();
+      dbStruct_.reset(db);
     }
 
+    Wt::Dbo::Transaction transaction(db->session);
     std::vector<Wt::Dbo::ptr<World> > results;
     results.reserve(n);
     for (int i = 0; i < n; ++i) {
@@ -250,7 +227,7 @@ public:
 
   virtual void resolveString(const std::string& varName, const std::vector<Wt::WString>& vars, std::ostream& result) {
     if (varName == "id")
-      format(result, Wt::WString::fromUTF8(boost::lexical_cast<std::string>(it_->id())), Wt::XHTMLUnsafeText);
+      result << it_->id();
     else if (varName == "message")
       format(result, Wt::WString::fromUTF8((*it_)->message));
     else
@@ -259,8 +236,6 @@ public:
 };
 
 class FortuneResource : public Wt::WResource {
-private:
-  boost::thread_specific_ptr<DbStruct> dbStruct_;
 public:
   virtual void handleRequest(const Wt::Http::Request &request, Wt::Http::Response &response) {
     response.setMimeType("text/html; charset=utf-8");
@@ -268,13 +243,11 @@ public:
 
     DbStruct* db = dbStruct_.get();
     if (!db) {
-      std::lock_guard<std::mutex> lock(mtx);
-      if (!db) {
-        db = new DbStruct();
-        dbStruct_.reset(db);
-      }
+      db = new DbStruct();
+      dbStruct_.reset(db);
     }
 
+    Wt::Dbo::Transaction transaction(db->session);
     Fortunes fortunes = db->session.find<Fortune>();
     VFortunes vFortunes;
     for (Fortunes::const_iterator i = fortunes.begin(); i != fortunes.end(); ++i)
@@ -293,8 +266,6 @@ public:
 };
 
 class UpdateResource : public Wt::WResource {
-private:
-  boost::thread_specific_ptr<DbStructNoTransaction> dbStruct_;
 public:
   virtual void handleRequest(const Wt::Http::Request &request, Wt::Http::Response &response) {
     int n;
@@ -311,13 +282,10 @@ public:
     response.setMimeType("application/json");
     response.addHeader("Server", "Wt");
 
-    DbStructNoTransaction* db = dbStruct_.get();
+    DbStruct* db = dbStruct_.get();
     if (!db) {
-      std::lock_guard<std::mutex> lock(mtx);
-      if (!db) {
-        db = new DbStructNoTransaction();
-        dbStruct_.reset(db);
-      }
+      db = new DbStruct();
+      dbStruct_.reset(db);
     }
 
     std::vector<Wt::Dbo::ptr<World> > results;

+ 1 - 1
frameworks/C/haywire/benchmark_config

@@ -10,7 +10,7 @@
       "database": "None",
       "framework": "haywire",
       "language": "C",
-      "orm": "None",
+      "orm": "Raw",
       "platform": "haywire",
       "webserver": "None",
       "os": "Linux",

+ 74 - 4
frameworks/C/lwan/README.md

@@ -1,11 +1,82 @@
 # Lwan
 
-This is the configuration files to benchmark the [Lwan](http://lwan.ws)
+This is the configuration files to benchmark the [Lwan](http://lwan.ws/?src=twfb)
 web server/framework.
 
+## FAQ
+
+### Where's the source code for the benchmark?
+
+Source code for the benchmark itself is currently living in [in Lwan's
+repository](https://github.com/lpereira/lwan/tree/master/techempower) for
+practical reasons, but will move to [this repository right after Round 10 is
+complete](https://github.com/TechEmpower/FrameworkBenchmarks/issues/1372).
+
+In any case, the script to install the framework in the test machines [pulls
+a specific snapshot of the Lwan source
+code](https://github.com/lpereira/lwan/tree/49607addb31879e2aa2b701317773674662315aa),
+including the benchmark code; and, due to the nature of Git, it's not
+possible to alter that code without changing which commit hash to checkout
+in this repository.
+
+### The JSON test RPS value seems ridiculous; is Lwan cheating?
+
+Come on. There's no optimization without cheating. There's a somewhat
+[detailed blog post about
+this](http://tia.mat.br/blog/html/2014/10/06/life_of_a_http_request.html?src=twfb).
+However, that level of cheating is considered by Lwan's author to be fair
+game, since it's not related to the benchmark code itself.
+
+In fact, the serialization library has been picked solely because it was
+available in the [CCAN](http://ccodearchive.net/).  It's written by [Joseph
+A.  Adams](http://ccodearchive.net/info/json.html), and has been slightly
+tweaked to fix some compiler warnings and a few other minor changes.  No
+major optimization or trickery has been made there: it's essentially the
+same code.  Props to him for a clean code that performs well.
+
+It's all open source anyway, feel free to go ahead and inspect the code.
+
+### The database results aren't that good. Why?
+
+The database tests are included for completeness sake. The database
+abstraction layer (which works with SQLite and MySQL) was written
+specifically for this benchmark, and is completely synchronous: while
+one query is being performed, all other clients wait.
+
+So the uninspiring results are expected. Database connectivity is
+important and will eventually be revisited.
+
+### I've seen the preliminary results and Lwan didn't fare well in the plaintext benchmark. Is there a reason why?
+
+These benchmarks are performed using pipelined requests. For practical
+reasons (almost no client supports them, at least by default), this was not
+implemented in Lwan: the server was dropping the request buffer and waiting
+for the next request to come in, while `wrk` was waiting for responses to
+come out, eventually timeouting and sending more pipelined requests, only to
+repeat, until the test actually ended.
+
+Pipelining has been implemented in a hurry to get included in Round 10.
+
+### The results are pretty good, can I use this in my next web app?
+
+Writing web apps in C? Only if you're Crazy. (The uppercase C is not a typo.)
+
+Seriously, Lwan is just a toy.  It's an experiment.  Most things you'll need
+from real frameworks won't be available.  You'll have a hard time trying to do
+the simplest things.  There are far more important things to look for while
+picking a framework, and performance, while important, is not the most
+important factor.  However, if you're feeling adventurous, know that Lwan is
+free software, and is very open to pull requests.
+
+### I have other questions, is there a FAQ somewhere else?
+
+Sure there is. [See Lwan's web page](http://lwan.ws/?src=twfb) or contact the author
+directly.
+
 ## Requirements
 
-GCC, SQLite 3.7, Linux 3.0, optionally jemalloc or tcmalloc.
+GCC, SQLite 3.7, MySQL/MariaDB client libraries, Lua 5.1/LuaJit 2.0, Linux 3.0,
+optionally jemalloc or tcmalloc.
 
 ## Tests available
 
@@ -29,7 +100,6 @@ URL: /fortunes
 
 URL: /plaintext
 
-
 ## Contact
 
-Leandro Pereira <[email protected]>
+[Leandro Pereira](http://tia.mat.br/?src=twfb) <[[email protected]](mailto:[email protected])>

+ 19 - 4
frameworks/C/lwan/benchmark_config

@@ -1,13 +1,30 @@
 {
   "framework": "lwan",
   "tests": [{
+    "default": {
+      "setup_file": "setup",
+      "plaintext_url": "/plaintext",
+      "json_url": "/json",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Platform",
+      "database": "None",
+      "framework": "lwan",
+      "language": "C",
+      "orm": "Raw",
+      "platform": "Lwan",
+      "webserver": "Lwan",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "Lwan",
+      "notes": "",
+      "versus": ""
+    },
     "sqlite": {
       "setup_file": "setup",
       "db_url": "/db",
       "query_url": "/queries?queries=",
       "fortune_url": "/fortunes",
-      "plaintext_url": "/plaintext",
-      "json_url": "/json",
       "port": 8080,
       "approach": "Realistic",
       "classification": "Platform",
@@ -28,8 +45,6 @@
       "db_url": "/db",
       "query_url": "/queries?queries=",
       "fortune_url": "/fortunes",
-      "plaintext_url": "/plaintext",
-      "json_url": "/json",
       "port": 8080,
       "approach": "Realistic",
       "classification": "Platform",

+ 1 - 1
frameworks/C/lwan/install.sh

@@ -1,6 +1,6 @@
 #!/bin/bash
 
-REV='eb96604657dd940ecb70b56fef4279077e3f9c21'
+REV='49607addb31879e2aa2b701317773674662315aa'
 
 INSTALLED_FILE="${IROOT}/lwan-${REV}.installed"
 RETCODE=$(fw_exists ${INSTALLED_FILE})

+ 1 - 1
frameworks/Go/beego/benchmark_config

@@ -12,7 +12,7 @@
       "database": "MySQL",
       "framework": "beego",
       "language": "Go",
-      "orm": "beego ORM",
+      "orm": "Micro",
       "platform": "Go",
       "webserver": "None",
       "os": "Linux",

+ 1 - 1
frameworks/Groovy/grails/README.md

@@ -4,7 +4,7 @@ This is the Grails portion of a [benchmarking test suite](../) comparing a varie
 
 ## Infrastructure Software Versions
 The tests were run with:
-* [Grails 2.4.2](http://grails.org/)
+* [Grails 2.4.4](http://grails.org/)
 
 ## Test URLs
 

+ 0 - 4
frameworks/Groovy/grails/bash_profile.sh

@@ -1,4 +0,0 @@
-export JAVA_HOME=/usr/lib/jvm/java-1.7.0-openjdk-amd64
-export RESIN_HOME=${IROOT}/resin-4.0.41
-
-export GRAILS_PATH=${IROOT}/grails-2.4.2/bin/

+ 1 - 1
frameworks/Groovy/grails/hello/application.properties

@@ -1,6 +1,6 @@
 #Grails Metadata file
 #Tue Feb 25 10:29:09 EET 2014
-app.grails.version=2.4.2
+app.grails.version=2.4.4
 app.name=hello
 app.servlet.version=2.5
 app.version=0.1

+ 4 - 4
frameworks/Groovy/grails/hello/grails-app/conf/BuildConfig.groovy

@@ -45,7 +45,7 @@ grails.project.dependency.resolution = {
         inherits true // Whether to inherit repository definitions from plugins
         grailsPlugins()
         grailsHome()
-		mavenLocal()
+        mavenLocal()
         grailsCentral()
         mavenCentral()
 
@@ -60,11 +60,11 @@ grails.project.dependency.resolution = {
     dependencies {
         // specify dependencies here under either 'build', 'compile', 'runtime', 'test' or 'provided' scopes eg.
 
-        runtime 'mysql:mysql-connector-java:5.1.29'
+        runtime 'mysql:mysql-connector-java:5.1.34'
     }
 
     plugins {
-        runtime ":hibernate:3.6.10.16"
+        runtime ":hibernate:3.6.10.18"
         //runtime ":jquery:1.10.2"
         //runtime ":resources:1.2.1"
 
@@ -73,6 +73,6 @@ grails.project.dependency.resolution = {
         //runtime ":cached-resources:1.0"
         //runtime ":yui-minify-resources:0.1.4"
 
-        build ":tomcat:7.0.54"
+        build ":tomcat:7.0.55.2"
     }
 }

+ 3 - 0
frameworks/Groovy/grails/hello/grails-app/conf/mysql-connection.properties

@@ -58,3 +58,6 @@ maintainTimeStats=false
 # timeouts for TCP/IP
 connectTimeout=15000
 socketTimeout=120000
+
+# enable batch mode
+rewriteBatchedStatements=true

+ 3 - 6
frameworks/Groovy/grails/hello/grails-app/controllers/hello/HelloController.groovy

@@ -1,16 +1,13 @@
 package hello
 
+import grails.compiler.GrailsCompileStatic
 import grails.converters.JSON
-import grails.transaction.Transactional
-import groovy.transform.CompileStatic
-import groovy.transform.TypeCheckingMode;
 
 import java.util.concurrent.ThreadLocalRandom
 
-import org.springframework.transaction.annotation.Propagation;
-import org.hibernate.Session;
+import org.hibernate.Session
 
-@CompileStatic
+@GrailsCompileStatic
 class HelloController {
 
     def index() {

+ 3 - 0
frameworks/Groovy/grails/hello/grails-app/domain/hello/Fortune.groovy

@@ -1,5 +1,8 @@
 package hello
 
+import grails.compiler.GrailsCompileStatic
+
+@GrailsCompileStatic
 class Fortune {
     Integer id
     String message

+ 3 - 0
frameworks/Groovy/grails/hello/grails-app/domain/hello/World.groovy

@@ -1,5 +1,8 @@
 package hello
 
+import grails.compiler.GrailsCompileStatic
+
+@GrailsCompileStatic
 class World {
     Integer id
     Integer randomNumber

+ 0 - 85
frameworks/Groovy/grails/hello/src/groovy/org/codehaus/groovy/grails/plugins/codecs/JSONEncoder.java

@@ -1,85 +0,0 @@
-/*
- * Copyright 2013 the original author or authors.
- *
- * 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 org.codehaus.groovy.grails.plugins.codecs;
-
-import org.apache.commons.lang.StringUtils;
-import org.codehaus.groovy.grails.support.encoding.CodecIdentifier;
-import org.codehaus.groovy.grails.support.encoding.DefaultCodecIdentifier;
-
-/**
- * Escapes characters in JSON output
- *
- * @author Lari Hotari
- * @since 2.3.4
- */
-public class JSONEncoder extends AbstractCharReplacementEncoder {
-    public static final CodecIdentifier JSON_CODEC_IDENTIFIER = new DefaultCodecIdentifier(
-            "JSON", "Json") {
-        public boolean isEquivalent(CodecIdentifier other) {
-            return super.isEquivalent(other) || JavaScriptEncoder.JAVASCRIPT_CODEC_IDENTIFIER.getCodecName().equals(other.getCodecName());
-        };
-    };
-
-    public JSONEncoder() {
-        super(JSON_CODEC_IDENTIFIER);
-    }
-
-    /* (non-Javadoc)
-     * @see org.codehaus.groovy.grails.plugins.codecs.AbstractCharReplacementEncoder#escapeCharacter(char, char)
-     */
-    @Override
-    protected String escapeCharacter(char ch, char previousChar) {
-        switch (ch) {
-            case '"':
-                return "\\\"";
-            case '\\':
-                return "\\\\";
-            case '\t':
-                return "\\t";
-            case '\n':
-                return "\\n";
-            case '\r':
-                return "\\r";
-            case '\f':
-                return "\\f";
-            case '\b':
-                return "\\b";
-            case '\u000B': // vertical tab: http://bclary.com/2004/11/07/#a-7.8.4
-                return "\\v";
-            case '\u2028':
-                return "\\u2028"; // Line separator
-            case '\u2029':
-                return "\\u2029"; // Paragraph separator
-            case '/':
-                // preserve special handling that exists in JSONObject.quote to improve security if JSON is embedded in HTML document
-                // prevents outputting "</" gets outputted with unicode escaping for the slash
-                if (previousChar == '<') {
-                    return "\\u002f"; 
-                }
-                break;
-        }
-        if(ch < ' ') {
-            // escape all other control characters
-            return "\\u" + StringUtils.leftPad(Integer.toHexString(ch), 4, '0');
-        }
-        return null;
-    }
-
-    @Override
-    public boolean isApplyToSafelyEncoded() {
-        return true;
-    }
-}

+ 5 - 1
frameworks/Groovy/grails/install.sh

@@ -1,3 +1,7 @@
 #!/bin/bash
+export JAVA_HOME=/usr/lib/jvm/java-1.7.0-openjdk-amd64
+export RESIN_HOME=${IROOT}/resin-4.0.41
 
-fw_depends grails resin 
+export GRAILS_PATH=${IROOT}/grails-2.4.4/bin/
+
+fw_depends grails resin

+ 6 - 1
frameworks/Groovy/grails/setup.sh

@@ -1,4 +1,8 @@
 #!/bin/bash
+export JAVA_HOME=/usr/lib/jvm/java-1.7.0-openjdk-amd64
+export RESIN_HOME=${IROOT}/resin-4.0.41
+
+export GRAILS_PATH=${IROOT}/grails-2.4.4/bin/
 
 sed -i 's|jdbc:mysql://.*:3306|jdbc:mysql://'"${DBHOST}"':3306|g' hello/grails-app/conf/DataSource.groovy
 
@@ -6,8 +10,9 @@ export PATH=${GRAILS_PATH}:$PATH
 export GRAILS_AGENT_CACHE_DIR=${IROOT}/.grails/.slcache
 
 cd hello
+grails -Dgrails.work.dir=${IROOT}/.grails -non-interactive -plain-output refresh-dependencies
 grails -Dgrails.work.dir=${IROOT}/.grails -non-interactive -plain-output compile
 grails -Dgrails.work.dir=${IROOT}/.grails prod -non-interactive -plain-output war
 rm -rf $RESIN_HOME/webapps/*
 cp target/hello-0.1.war $RESIN_HOME/webapps/grails.war
-$RESIN_HOME/bin/resinctl start
+$RESIN_HOME/bin/resinctl start

+ 18 - 14
frameworks/Java/activeweb/benchmark_config

@@ -4,15 +4,19 @@
     "default": {
       "setup_file": "setup",
       "json_url": "/activeweb/json",
+      "db_url": "/activeweb/db",
+      "query_url": "/activeweb/queries?queries=",
+      "fortune_url": "/activeweb/fortunes",
+      "update_url": "/activeweb/updates?queries=",
       "plaintext_url": "/activeweb/plaintext",
       "port": 8080,
       "approach": "Realistic",
-      "classification": "Platform",
-      "database": "None",
+      "classification": "Fullstack",
+      "database": "MySQL",
       "framework": "activeweb",
       "language": "Java",
-      "orm": "Raw",
-      "platform": "ActiveWeb",
+      "orm": "Micro",
+      "platform": "Servlet",
       "webserver": "Resin",
       "os": "Linux",
       "database_os": "Linux",
@@ -20,24 +24,24 @@
       "notes": "",
       "versus": "servlet"
     },
-    "raw": {
+    "jackson": {
       "setup_file": "setup",
-      "db_url": "/activeweb/db",
-      "query_url": "/activeweb/queries?queries=",
-      "fortune_url": "/activeweb/fortunes",
-      "update_url": "/activeweb/updates?queries=",
+      "json_url": "/activeweb/json/jackson",
+      "db_url": "/activeweb/db/jackson",
+      "query_url": "/activeweb/queries/jackson?queries=",
+      "update_url": "/activeweb/updates/jackson?queries=",
       "port": 8080,
       "approach": "Realistic",
-      "classification": "Platform",
+      "classification": "Fullstack",
       "database": "MySQL",
-      "framework": "ActiveWeb",
+      "framework": "activeweb",
       "language": "Java",
-      "orm": "Raw",
-      "platform": "ActiveWeb",
+      "orm": "Micro",
+      "platform": "Servlet",
       "webserver": "Resin",
       "os": "Linux",
       "database_os": "Linux",
-      "display_name": "activeweb",
+      "display_name": "ActiveWeb",
       "notes": "",
       "versus": "servlet"
     }

+ 48 - 11
frameworks/Java/activeweb/pom.xml

@@ -9,7 +9,8 @@
     <name>ActiveWeb Benchmark App</name>
 
     <properties>
-        <activeweb.version>1.9</activeweb.version>
+        <activeweb.version>1.11</activeweb.version>
+        <activejdbc.version>1.4.10</activejdbc.version>
     </properties>
 
     <build>
@@ -18,7 +19,7 @@
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-surefire-plugin</artifactId>
-                <version>2.14.1</version>
+                <version>2.18.1</version>
                 <configuration>
                     <reportFormat>brief</reportFormat>
                     <trimStackTrace>true</trimStackTrace>
@@ -51,12 +52,18 @@
                             <maxIdleTime>1000</maxIdleTime>
                         </connector>
                     </connectors>
+                    <!--<systemProperties>-->
+                        <!--<systemProperty>-->
+                            <!--<name>active_reload</name>-->
+                            <!--<value>true</value>-->
+                        <!--</systemProperty>-->
+                    <!--</systemProperties>-->
                 </configuration>
             </plugin>
             <plugin>
                 <groupId>org.javalite</groupId>
                 <artifactId>activejdbc-instrumentation</artifactId>
-                <version>1.4.9</version>
+                <version>${activejdbc.version}</version>
                 <executions>
                     <execution>
                         <phase>process-classes</phase>
@@ -73,7 +80,7 @@
         <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
-            <version>4.8.1</version>
+            <version>4.12</version>
             <scope>test</scope>
         </dependency>
         <dependency>
@@ -81,6 +88,11 @@
             <artifactId>activeweb</artifactId>
             <version>${activeweb.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.javalite</groupId>
+            <artifactId>activejdbc</artifactId>
+            <version>${activejdbc.version}</version>
+        </dependency>
         <dependency>
             <groupId>org.javalite</groupId>
             <artifactId>activeweb-testing</artifactId>
@@ -98,18 +110,43 @@
             <artifactId>slf4j-simple</artifactId>
             <version>1.7.5</version>
         </dependency>
-
         <dependency>
             <groupId>com.fasterxml.jackson.core</groupId>
             <artifactId>jackson-core</artifactId>
-            <version>2.3.1</version>
+            <version>2.4.4</version>
         </dependency>
-
         <dependency>
-          <groupId>com.fasterxml.jackson.core</groupId>
-          <artifactId>jackson-databind</artifactId>
-          <version>2.3.1</version>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+            <version>2.4.4</version>
         </dependency>
-
     </dependencies>
+
+    <repositories>
+        <repository>
+            <id>javaLite-snapshots</id>
+            <name>JavaLite Snapshots</name>
+            <url>http://repo.javalite.io/</url>
+            <releases>
+                <enabled>false</enabled>
+            </releases>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+        </repository>
+    </repositories>
+    <pluginRepositories>
+        <pluginRepository>
+            <id>javaLite-plugin-snapshots</id>
+            <name>JavaLite Plugin Snapshots</name>
+            <url>http://repo.javalite.io/</url>
+            <releases>
+                <enabled>false</enabled>
+            </releases>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+        </pluginRepository>
+    </pluginRepositories>
+
 </project>

+ 14 - 14
frameworks/Java/activeweb/source_code

@@ -1,14 +1,14 @@
-./src/main/java/app/config/AppControllerConfig.java
-./src/main/java/app/config/RouteConfig.java
-./src/main/java/app/config/FreeMarkerConfig.java
-./src/main/java/app/config/DbConfig.java
-./src/main/java/app/config/AppBootstrap.java
-./src/main/java/app/models/World.java
-./src/main/java/app/models/Fortune.java
-./src/main/java/app/controllers/PlaintextController.java
-./src/main/java/app/controllers/JsonController.java
-./src/main/java/app/controllers/DatabaseController.java
-./src/main/java/app/controllers/FortunesController.java
-./src/main/java/app/controllers/QueriesController.java
-./src/main/java/app/controllers/HomeController.java
-./src/main/java/app/controllers/UpdatesController.java
+./activeweb/src/main/java/app/config/AppBootstrap.java
+./activeweb/src/main/java/app/config/AppControllerConfig.java
+./activeweb/src/main/java/app/config/DbConfig.java
+./activeweb/src/main/java/app/config/RouteConfig.java
+./activeweb/src/main/java/app/controllers/DbController.java
+./activeweb/src/main/java/app/controllers/FortunesController.java
+./activeweb/src/main/java/app/controllers/HomeController.java
+./activeweb/src/main/java/app/controllers/JsonController.java
+./activeweb/src/main/java/app/controllers/PlaintextController.java
+./activeweb/src/main/java/app/controllers/QueriesController.java
+./activeweb/src/main/java/app/controllers/UpdatesController.java
+./activeweb/src/main/java/app/models/Fortune.java
+./activeweb/src/main/java/app/models/Message.java
+./activeweb/src/main/java/app/models/World.java

+ 2 - 4
frameworks/Java/activeweb/src/main/java/app/config/AppBootstrap.java

@@ -17,15 +17,13 @@ package app.config;
 
 import org.javalite.activeweb.AppContext;
 import org.javalite.activeweb.Bootstrap;
-
-import com.google.inject.Guice;
-import org.javalite.activeweb.Configuration;
+import org.javalite.templator.TemplatorConfig;
 
 /**
  * @author Igor Polevoy
  */
 public class AppBootstrap extends Bootstrap {
     public void init(AppContext context) {
-        Configuration.setUseDefaultLayoutForErrors(true);
+        TemplatorConfig.instance().cacheTemplates(true);
     }
 }

+ 2 - 2
frameworks/Java/activeweb/src/main/java/app/config/AppControllerConfig.java

@@ -16,7 +16,7 @@ limitations under the License.
 package app.config;
 
 
-import app.controllers.DatabaseController;
+import app.controllers.DbController;
 import app.controllers.FortunesController;
 import app.controllers.QueriesController;
 import app.controllers.UpdatesController;
@@ -33,7 +33,7 @@ public class AppControllerConfig extends AbstractControllerConfig {
     public void init(AppContext context) {
 //        addGlobalFilters(new TimingFilter()); for speed - not sure how logging is configured
 
-        add(new DBConnectionFilter()).to(DatabaseController.class, QueriesController.class,
+        add(new DBConnectionFilter()).to(DbController.class, QueriesController.class,
                 FortunesController.class, UpdatesController.class);
     }
 }

+ 0 - 30
frameworks/Java/activeweb/src/main/java/app/config/FreeMarkerConfig.java

@@ -1,30 +0,0 @@
-/*
-Copyright 2009-2010 Igor Polevoy 
-
-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 app.config;
-
-import org.javalite.activeweb.freemarker.AbstractFreeMarkerConfig;
-
-/**
- * @author Igor Polevoy
- */
-public class FreeMarkerConfig extends org.javalite.activeweb.freemarker.AbstractFreeMarkerConfig {
-    @Override
-    public void init() {
-        //this is to override a strange FreeMarker default processing of numbers 
-        getConfiguration().setNumberFormat("0.##");
-    }
-}

+ 1 - 4
frameworks/Java/activeweb/src/main/java/app/config/RouteConfig.java

@@ -20,13 +20,10 @@ limitations under the License.
 
 package app.config;
 
-import app.controllers.DatabaseController;
 import org.javalite.activeweb.AbstractRouteConfig;
 import org.javalite.activeweb.AppContext;
 
 public class RouteConfig extends AbstractRouteConfig {
-    @Override
-    public void init(AppContext appContext) {
-        route("/db").to(DatabaseController.class);
+    @Override public void init(AppContext appContext) {
     }
 }

+ 0 - 39
frameworks/Java/activeweb/src/main/java/app/controllers/DatabaseController.java

@@ -1,39 +0,0 @@
-/*
-Copyright 2009-2010 Igor Polevoy 
-
-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. 
-*/
-
-/**
- * @author Igor Polevoy: 12/18/13 4:36 PM
- */
-
-package app.controllers;
-
-import app.models.World;
-import org.javalite.activeweb.AppController;
-
-import java.util.Date;
-import java.util.Random;
-import java.util.concurrent.ThreadLocalRandom;
-
-public class DatabaseController extends AppController {
-    public void index() {
-
-        String json = World.findById(ThreadLocalRandom.current().nextInt(10000)).toJson(false, "id", "randomNumber");
-
-        respond(json).contentType("application/json")
-                .header("Content-Length", String.valueOf(json.length()))
-                .header("Date", new Date().toString());
-    }
-}

+ 40 - 0
frameworks/Java/activeweb/src/main/java/app/controllers/DbController.java

@@ -0,0 +1,40 @@
+/*
+Copyright 2009-2015 Igor Polevoy
+
+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 app.controllers;
+
+import app.models.World;
+import java.io.IOException;
+import org.javalite.activeweb.AppController;
+
+import java.util.concurrent.ThreadLocalRandom;
+
+/**
+ * @author Igor Polevoy: 12/18/13 4:36 PM
+ * @author Eric Nielsen
+ */
+public class DbController extends AppController {
+    public void index() {
+        respond(World.findById(randomNumber()).toJson(false, "id", "randomNumber")).contentType("application/json");
+    }
+
+    public void jackson() throws IOException {
+        JsonController.WRITER.writeValue(outputStream("application/json"), World.findById(randomNumber()));
+    }
+
+    protected int randomNumber(){
+        return ThreadLocalRandom.current().nextInt(10000) + 1;
+    }
+}

+ 16 - 19
frameworks/Java/activeweb/src/main/java/app/controllers/FortunesController.java

@@ -1,23 +1,18 @@
 /*
-Copyright 2009-2010 Igor Polevoy 
+Copyright 2009-2015 Igor Polevoy
 
-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 
+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 
+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. 
+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.
 */
-
-/**
- * @author Igor Polevoy: 12/18/13 9:11 PM
- */
-
 package app.controllers;
 
 import app.models.Fortune;
@@ -25,17 +20,19 @@ import org.javalite.activeweb.AppController;
 
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.Date;
 import java.util.List;
 
+/**
+ * @author Igor Polevoy: 12/18/13 9:11 PM
+ * @author Eric Nielsen
+ */
 public class FortunesController extends AppController {
-
     public void index() {
         List<Fortune> dbFortunes = Fortune.findAll();
         List<Fortune> fortunes = new ArrayList<Fortune>(dbFortunes);
-        fortunes.add((Fortune) Fortune.create("id", 0, "message", "Additional fortune added at request time."));
+        fortunes.add(Fortune.<Fortune>create("id", 0, "message", "Additional fortune added at request time."));
         Collections.sort(fortunes);
         view("fortunes", fortunes);
-        render().noLayout();
+        render("/fortunes/index").noLayout();
     }
 }

+ 24 - 33
frameworks/Java/activeweb/src/main/java/app/controllers/JsonController.java

@@ -1,49 +1,40 @@
 /*
-Copyright 2009-2010 Igor Polevoy 
+Copyright 2009-2015 Igor Polevoy
 
-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 
+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 
+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. 
+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.
 */
-
-/**
- * @author Igor Polevoy: 12/18/13 3:51 PM
- */
-
 package app.controllers;
 
+import app.models.Message;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.ObjectWriter;
+import java.io.IOException;
 import org.javalite.activeweb.AppController;
 
-import java.io.IOException;
-import java.util.Date;
 
+/**
+ * @author Igor Polevoy: 12/18/13 3:51 PM
+ * @author Eric Nielsen
+ */
 public class JsonController extends AppController {
-    public void index() throws IOException {
-        String json = new ObjectMapper().writeValueAsString(new Message("Hello, World!"));
-        respond(json)
-                .contentType("application/json")
-                .header("Content-Length", String.valueOf(json.length()))
-                .header("Date", new Date().toString());
-    }
-
-    public static final class Message {
-        private final String message;
+    static final ObjectWriter WRITER = new ObjectMapper().writer();
 
-        private Message(String message) {
-            this.message = message;
-        }
+    public void index() {
+        view("message", new Message("Hello, World!"));
+        render("/json/index").noLayout().contentType("application/json");
+    }
 
-        public String getMessage() {
-            return message;
-        }
+    public void jackson() throws IOException {
+        WRITER.writeValue(outputStream("application/json"), new Message("Hello, World!"));
     }
 }

+ 15 - 22
frameworks/Java/activeweb/src/main/java/app/controllers/PlaintextController.java

@@ -1,35 +1,28 @@
 /*
-Copyright 2009-2010 Igor Polevoy 
+Copyright 2009-2015 Igor Polevoy
 
-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 
+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 
+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. 
+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.
 */
-
-/**
- * @author Igor Polevoy: 12/19/13 1:23 AM
- */
-
 package app.controllers;
 
 import org.javalite.activeweb.AppController;
 
-import java.util.Date;
-
+/**
+ * @author Igor Polevoy: 12/19/13 1:23 AM
+ * @author Eric Nielsen
+ */
 public class PlaintextController extends AppController {
     public void index() {
-        String message = "Hello, World!";
-        respond(message)
-                .contentType("text/plain")
-                .header("Content-Length", String.valueOf(message.length()))
-                .header("Date", new Date().toString());
+        respond("Hello, World!").contentType("text/plain");
     }
 }

+ 26 - 32
frameworks/Java/activeweb/src/main/java/app/controllers/QueriesController.java

@@ -1,40 +1,42 @@
 /*
-Copyright 2009-2010 Igor Polevoy 
+Copyright 2009-2015 Igor Polevoy
 
-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 
+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 
+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. 
+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.
 */
-
-/**
- * @author Igor Polevoy: 12/18/13 4:36 PM
- */
-
 package app.controllers;
 
 import app.models.World;
-import org.javalite.activeweb.AppController;
+import java.io.IOException;
 
 import java.util.ArrayList;
-import java.util.Date;
-import java.util.LinkedList;
 import java.util.List;
-import java.util.concurrent.ThreadLocalRandom;
 
-public class QueriesController extends AppController {
+/**
+ * @author Igor Polevoy: 12/18/13 4:36 PM
+ * @author Eric Nielsen
+ */
+public class QueriesController extends DbController {
+    @Override public void index() {
+        view("worlds", getWorlds());
+        render("/queries/index").contentType("application/json");
+    }
 
-    public void index() {
+    @Override public void jackson() throws IOException {
+        JsonController.WRITER.writeValue(outputStream("application/json"), getWorlds());
+    }
 
-        view("worlds", getWorlds());
-        render().contentType("application/json").header("Date", new Date().toString());
+    @Override protected String getLayout() {
+        return null;
     }
 
     protected List<World> getWorlds() {
@@ -46,7 +48,7 @@ public class QueriesController extends AppController {
         return worlds;
     }
 
-    public int getQueries() {
+    protected int getQueries() {
         int queries;
         try {
             queries = Integer.parseInt(param("queries"));
@@ -60,12 +62,4 @@ public class QueriesController extends AppController {
         }
         return queries;
     }
-    protected int randomNumber(){
-        return ThreadLocalRandom.current().nextInt(10000) + 1;
-    }
-
-    @Override
-    protected String getLayout() {
-        return null;
-    }
 }

+ 18 - 21
frameworks/Java/activeweb/src/main/java/app/controllers/UpdatesController.java

@@ -1,38 +1,35 @@
 /*
-Copyright 2009-2010 Igor Polevoy 
+Copyright 2009-2015 Igor Polevoy
 
-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 
+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 
+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. 
+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.
 */
-
-/**
- * @author Igor Polevoy: 12/18/13 9:51 PM
- */
-
 package app.controllers;
 
 import app.models.World;
-import org.javalite.activeweb.AppController;
 
 import java.util.List;
-import java.util.concurrent.ThreadLocalRandom;
 
+/**
+ * @author Igor Polevoy: 12/18/13 9:51 PM
+ * @author Eric Nielsen
+ */
 public class UpdatesController extends QueriesController {
-    public void index() {
-        List<World> worlds = getWorlds();
+
+    @Override protected List<World> getWorlds() {
+        List<World> worlds = super.getWorlds();
         for (World world : worlds) {
             world.set("randomNumber", randomNumber()).saveIt();
         }
-        view("worlds", worlds);
-        render("/queries/index"); //same template
+        return worlds;
     }
 }

+ 1 - 1
frameworks/Java/activeweb/src/main/java/app/models/Fortune.java

@@ -25,7 +25,7 @@ import org.javalite.activejdbc.annotations.Table;
 
 @Table("Fortune")
 public class Fortune extends Model implements Comparable<Fortune> {
-    public int compareTo(Fortune other) {
+    @Override public int compareTo(Fortune other) {
         return getString("message").compareTo(other.getString("message"));
     }
 }

+ 38 - 0
frameworks/Java/activeweb/src/main/java/app/models/Message.java

@@ -0,0 +1,38 @@
+/*
+Copyright 2009-2015 Igor Polevoy
+
+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 app.models;
+
+/**
+ * @author Eric Nielsen
+ */
+public class Message {
+    private String message;
+
+    public Message() {
+    }
+
+    public Message(String message) {
+        this.message = message;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+}

+ 19 - 17
frameworks/Java/activeweb/src/main/java/app/models/World.java

@@ -1,30 +1,32 @@
 /*
-Copyright 2009-2010 Igor Polevoy 
+Copyright 2009-2015 Igor Polevoy
 
-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 
+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 
+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. 
+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.
 */
-
-/**
- * @author Igor Polevoy: 12/18/13 4:32 PM
- */
-
 package app.models;
 
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import org.javalite.activejdbc.Model;
 import org.javalite.activejdbc.annotations.Table;
 
-
+/**
+ * @author Igor Polevoy: 12/18/13 4:32 PM
+ * @author Eric Nielsen
+ */
 @Table("World")
+@JsonIgnoreProperties({"frozen", "idName", "longId", "new", "valid"})
 public class World extends Model {
-
+    public Object getRandomNumber() {
+        return get("randomNumber");
+    }
 }

+ 1 - 0
frameworks/Java/activeweb/src/main/resources/activeweb.properties

@@ -0,0 +1 @@
+templateManager=org.javalite.activeweb.templator.TemplatorManager

+ 0 - 20
frameworks/Java/activeweb/src/main/webapp/WEB-INF/views/fortunes/index.ftl

@@ -1,20 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head><title>Fortunes</title></head>
-<body>
-<table>
-    <tr>
-        <th>id</th>
-        <th>message</th>
-    </tr>
-
-<#list fortunes as fortune>
-    <tr>
-        <td>${fortune.id}</td>
-        <td>${fortune.message?html}</td>
-    </tr>
-</#list>
-
-</table>
-</body>
-</html>

+ 1 - 0
frameworks/Java/activeweb/src/main/webapp/WEB-INF/views/fortunes/index.html

@@ -0,0 +1 @@
+<!DOCTYPE html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr><#list fortunes as fortune ><tr><td>${fortune.id}</td><td>${fortune.message esc}</td></tr></#list></table></body></html>

+ 0 - 0
frameworks/Java/activeweb/src/main/webapp/WEB-INF/views/home/index.ftl → frameworks/Java/activeweb/src/main/webapp/WEB-INF/views/home/index.html


+ 1 - 0
frameworks/Java/activeweb/src/main/webapp/WEB-INF/views/json/index.html

@@ -0,0 +1 @@
+{"message":"${message.message}"}

+ 10 - 5
frameworks/Java/activeweb/src/main/webapp/WEB-INF/views/layouts/default_layout.ftl → frameworks/Java/activeweb/src/main/webapp/WEB-INF/views/layouts/default_layout.html

@@ -1,21 +1,26 @@
-<#setting url_escaping_charset='ISO-8859-1'>
-
 <html>
 <head>
     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
     <LINK href="${context_path}/css/main.css" rel="stylesheet" type="text/css"/>
     <script src="${context_path}/js/jquery-1.4.2.min.js" type="text/javascript"></script>
     <script src="${context_path}/js/aw.js" type="text/javascript"></script>
-    <title>ActiveWeb - <@yield to="title"/></title>
+    <title>ActiveWeb</title>
 </head>
 <body>
 
 <div class="main">
-<#include "header.ftl" >
+    <div class="header">
+        <h1><a href="${context_path}">ActiveWeb Benchmark Application</a></h1>
+    </div>
+
+
     <div class="content">
     ${page_content}
     </div>
-<#include "footer.ftl" >
+    <div class='footer'>
+        <p>2010 - 2015 Active Web.</p>
+    </div>
+
 </div>
 
 </body>

+ 0 - 3
frameworks/Java/activeweb/src/main/webapp/WEB-INF/views/layouts/footer.ftl

@@ -1,3 +0,0 @@
-<div class='footer'>
-    <p>2010 - 2013 Active Web. No Rights Reserved.</p>
-</div>

+ 0 - 4
frameworks/Java/activeweb/src/main/webapp/WEB-INF/views/layouts/header.ftl

@@ -1,4 +0,0 @@
-<div class="header">
-    <h1><a href="${context_path}">ActiveWeb Benchmark Application</a></h1>
-</div>
-

+ 0 - 7
frameworks/Java/activeweb/src/main/webapp/WEB-INF/views/queries/index.ftl

@@ -1,7 +0,0 @@
-<@compress single_line=true>
-[<#list worlds as w>
-{"id":${w.id},"randomNumber":${w.randomNumber}}
-<#if w_has_next>,</#if>
-</#list>
-]
-</@compress>

+ 1 - 0
frameworks/Java/activeweb/src/main/webapp/WEB-INF/views/queries/index.html

@@ -0,0 +1 @@
+[<#list worlds as w >{"id":${w.id},"randomNumber":${w.randomNumber}}<#if w_has_next >,</#if></#list>]

+ 0 - 0
frameworks/Java/activeweb/src/main/webapp/WEB-INF/views/system/404.ftl → frameworks/Java/activeweb/src/main/webapp/WEB-INF/views/system/404.html


+ 0 - 0
frameworks/Java/activeweb/src/main/webapp/WEB-INF/views/system/error.ftl → frameworks/Java/activeweb/src/main/webapp/WEB-INF/views/system/error.html


+ 0 - 46
frameworks/Java/activeweb/src/test/java/app/controllers/DatabaseControllerSpec.java

@@ -1,46 +0,0 @@
-/*
-Copyright 2009-2010 Igor Polevoy 
-
-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. 
-*/
-
-/**
- * @author Igor Polevoy: 12/18/13 4:42 PM
- */
-
-package app.controllers;
-
-
-import org.javalite.activeweb.DBControllerSpec;
-import org.junit.Test;
-
-import java.util.Map;
-
-public class DatabaseControllerSpec extends DBControllerSpec {
-
-    @Test
-    public void shouldRenderOneRecord(){
-
-        //execute controller
-        request().get("index");
-
-        //process result
-        Map result = JsonHelper.toMap(responseContent());
-
-        //test result
-        a(result.size()).shouldBeEqual(2);
-        a(result.get("id")).shouldNotBeNull();
-        a(result.get("randomNumber")).shouldNotBeNull();
-        a(contentType()).shouldBeEqual("application/json");
-    }
-}

+ 66 - 0
frameworks/Java/activeweb/src/test/java/app/controllers/DbControllerSpec.java

@@ -0,0 +1,66 @@
+/*
+Copyright 2009-2015 Igor Polevoy
+
+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 app.controllers;
+
+import org.junit.Test;
+
+import java.util.Map;
+import org.junit.Ignore;
+
+/**
+ * @author Igor Polevoy: 12/18/13 4:42 PM
+ * @author Eric Nielsen
+ */
+public class DbControllerSpec extends org.javalite.activeweb.DBControllerSpec {
+
+    @Test
+    public void shouldRenderOneRecord() {
+        //execute controller
+        request().get("index");
+        //process result
+        System.out.println(responseContent());
+        Map result = JsonHelper.toMap(responseContent());
+        //test result
+        a(result.size()).shouldBeEqual(2);
+        a(result.get("id")).shouldNotBeNull();
+        a(result.get("randomNumber")).shouldNotBeNull();
+        a(contentType()).shouldBeEqual("application/json");
+    }
+
+
+    @Test
+    public void shouldRenderOneRecordWithJackson() {
+        //execute controller
+        request().get("jackson");
+        //process result
+        System.out.println(responseContent());
+        Map result = JsonHelper.toMap(responseContent());
+        //test result
+        a(result.size()).shouldBeEqual(2);
+        a(result.get("id")).shouldNotBeNull();
+        a(result.get("randomNumber")).shouldNotBeNull();
+        a(contentType()).shouldBeEqual("application/json");
+    }
+
+    @Ignore
+    public void shouldRenderResponseOneMinute() {
+        long endMillis = System.currentTimeMillis() + 60*1000;
+        do {
+            request().get("index");
+            responseContent();
+        } while (System.currentTimeMillis() < endMillis);
+    }
+}

+ 48 - 0
frameworks/Java/activeweb/src/test/java/app/controllers/FortunesControllerSpec.java

@@ -0,0 +1,48 @@
+/*
+Copyright 2009-2015 Igor Polevoy
+
+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 app.controllers;
+
+import org.javalite.activeweb.DBControllerSpec;
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * @author Eric Nielsen
+ */
+public class FortunesControllerSpec extends DBControllerSpec {
+
+    @Test
+    public void shouldRenderHtml() {
+        request().integrateViews().get("index");
+        System.out.print(responseContent());
+        the(responseContent()).shouldContain(
+                "<tr><td>11</td><td>&lt;script&gt;alert(&quot;This should not be displayed in a browser alert box.&quot;);&lt;/script&gt;</td></tr>"
+                + "<tr><td>4</td><td>A bad random number generator: 1, 1, 1, 1, 1, 4.33e+67, 1, 1, 1</td></tr>"
+                + "<tr><td>5</td><td>A computer program does what you tell it to do, not what you want it to do.</td></tr>"
+                + "<tr><td>2</td><td>A computer scientist is someone who fixes things that aren&apos;t broken.</td></tr>");
+    }
+
+    @Ignore
+    @Test
+    public void shouldRenderHtmlOneMinute() {
+        long endMillis = System.currentTimeMillis() + 60*1000;
+        do {
+            request().integrateViews().get("index");
+            responseContent();
+        } while (System.currentTimeMillis() < endMillis);
+    }
+}

+ 33 - 26
frameworks/Java/activeweb/src/test/java/app/controllers/JsonControllerSpec.java

@@ -1,45 +1,52 @@
 /*
-Copyright 2009-2010 Igor Polevoy 
+Copyright 2009-2015 Igor Polevoy
 
-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 
+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 
+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. 
+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.
 */
-
-/**
- * @author Igor Polevoy: 12/18/13 3:59 PM
- */
-
 package app.controllers;
 
-import org.javalite.activeweb.Configuration;
 import org.javalite.activeweb.ControllerSpec;
+import org.junit.Ignore;
 import org.junit.Test;
 
-import java.util.Map;
 
+/**
+ * @author Igor Polevoy: 12/18/13 3:59 PM
+ * @author Eric Nielsen
+ */
 public class JsonControllerSpec extends ControllerSpec {
 
     @Test
     public void shouldRenderMessage() {
+        request().integrateViews().get("index");
+        the(responseContent()).shouldBeEqual("{\"message\":\"Hello, World!\"}");
+        the(contentType()).shouldBeEqual("application/json");
+    }
 
-        System.out.println("ACTIVE_ENV value ============>>>>" + Configuration.getEnv());
-        //execute controller
-        request().get("index");
-
-        //process result
-        Map result = JsonHelper.toMap(responseContent());
+    @Test
+    public void shouldRenderMessageWithJackson() {
+        request().get("jackson");
+        the(responseContent()).shouldBeEqual("{\"message\":\"Hello, World!\"}");
+        the(contentType()).shouldBeEqual("application/json");
+    }
 
-        //test result
-        a(result.get("message")).shouldBeEqual("Hello, World!");
-        a(contentType()).shouldBeEqual("application/json");
+    @Ignore
+    @Test
+    public void shouldRenderMessageOneMinute() {
+        long endMillis = System.currentTimeMillis() + 60*1000;
+        do {
+            request().integrateViews().get("index");
+            responseContent();
+        } while (System.currentTimeMillis() < endMillis);
     }
 }

+ 42 - 0
frameworks/Java/activeweb/src/test/java/app/controllers/PlaintextControllerSpec.java

@@ -0,0 +1,42 @@
+/*
+Copyright 2009-2015 Igor Polevoy
+
+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 app.controllers;
+
+import org.javalite.activeweb.ControllerSpec;
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * @author Eric Nielsen
+ */
+public class PlaintextControllerSpec extends ControllerSpec {
+
+    @Test
+    public void shouldRenderResponse() {
+        request().get("index");
+        the(responseContent()).shouldBeEqual("Hello, World!");
+    }
+
+    @Ignore
+    public void shouldRenderHtmlOneMinute() {
+        long endMillis = System.currentTimeMillis() + 60*1000;
+        do {
+            request().get("index");
+            responseContent();
+        } while (System.currentTimeMillis() < endMillis);
+    }
+}

+ 3 - 3
frameworks/Java/curacao/build.sbt

@@ -13,9 +13,9 @@ resolvers ++= Seq(
 )
 
 libraryDependencies ++= Seq(
-  "com.kolich.curacao" % "curacao" % "2.6.3" % "compile",
-  "com.kolich.curacao" % "curacao-gson" % "2.6.3" % "compile",
-  "org.eclipse.jetty" % "jetty-webapp" % "9.2.3.v20140905" % "compile",
+  "com.kolich.curacao" % "curacao" % "2.9-M1" % "compile",
+  "com.kolich.curacao" % "curacao-gson" % "2.9-M1" % "compile",
+  "org.eclipse.jetty" % "jetty-webapp" % "9.2.9.v20150224" % "compile",
   "javax.servlet" % "javax.servlet-api" % "3.0.1" % "provided",
   "org.slf4j" % "slf4j-api" % "1.7.2" % "compile",
   "ch.qos.logback" % "logback-core" % "1.0.7" % "compile",

+ 2 - 2
frameworks/Java/curacao/src/main/java/benchmark/Benchmarks.java

@@ -2,8 +2,8 @@ package benchmark;
 
 import benchmark.entities.HelloWorld;
 import com.kolich.curacao.annotations.Controller;
-import com.kolich.curacao.annotations.methods.RequestMapping;
-import com.kolich.curacao.handlers.requests.matchers.AntPathMatcher;
+import com.kolich.curacao.annotations.RequestMapping;
+import com.kolich.curacao.mappers.request.matchers.AntPathMatcher;
 
 @Controller
 public final class Benchmarks {

+ 5 - 5
frameworks/Java/gemini/Docroot/WEB-INF/GeminiHello.conf

@@ -87,19 +87,19 @@ DeploymentDescription = Production
 # specific configuration files.
 
 # MySQL/ConnectorJ
-db.Driver.Class = com.mysql.jdbc.Driver
-db.Driver.UrlPrefix = jdbc:mysql://
+db.Driver.Class = org.postgresql.Driver
+db.Driver.UrlPrefix = jdbc:postgresql://
 db.Driver.SupportsAbsolute = yes
 db.Driver.SupportsGetRow = yes
 db.Driver.Jdbc1 = no
 
-db.ConnectString = 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&useServerPrepStmts&enableQueryTimeouts=false&useUnbufferedIO=false&useReadAheadInput=false&maintainTimeStats=false&cacheRSMetadata=true
+db.ConnectString = 127.0.0.1:5432/hello_world?jdbcCompliantTruncation=false&elideSetAutoCommits=true&useLocalSessionState=true&cachePrepStmts=true&cacheCallableStmts=true&alwaysSendSetIsolation=false&prepStmtCacheSize=4096&cacheServerConfiguration=true&prepStmtCacheSqlLimit=2048&zeroDateTimeBehavior=convertToNull&traceProtocol=false&useServerPrepStmts&enableQueryTimeouts=false&useUnbufferedIO=false&useReadAheadInput=false&maintainTimeStats=false&cacheRSMetadata=true
 db.LoginName = benchmarkdbuser
 db.LoginPass = benchmarkdbpass
 
 # JTDS (Open source JDBC driver for Microsoft SQL Server)
-#db.Driver.Class = net.sourceforge.jtds.jdbc.Driver
-#db.Driver.UrlPrefix = jdbc:jtds:sqlserver://
+#db.Driver.Class = org.postgresql.Driver
+#db.Driver.UrlPrefix = jdbc:postgresql://
 #db.Driver.SupportsAbsolute = yes
 #db.Driver.SupportsGetRow = yes
 #db.Driver.Jdbc1 = no

BIN
frameworks/Java/gemini/Docroot/WEB-INF/lib/postgresql-9.4-1200.jdbc41.jar


+ 1 - 1
frameworks/Java/gemini/Docroot/WEB-INF/resin.xml

@@ -14,7 +14,7 @@
     </server>
 
     <host>
-      <web-app id="/" root-directory="/home/tfb/FrameworkBenchmarks/frameworks/Java/gemini/Docroot" />
+      <web-app id="/" root-directory="/home/knewman/FrameworkBenchmarks/frameworks/Java/gemini/Docroot" />
     </host>
 
   </cluster>

+ 41 - 3
frameworks/Java/gemini/benchmark_config

@@ -4,11 +4,28 @@
     "default": {
       "setup_file": "start",
       "json_url": "/",
+      "plaintext_url": "/plaintext",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "None",
+      "framework": "gemini",
+      "language": "Java",
+      "orm": "Micro",
+      "platform": "Servlet",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "gemini",
+      "notes": "",
+      "versus": "servlet"
+    },
+    "mysql": {
+      "setup_file": "start",
       "db_url": "/db",
       "query_url": "/query?queries=",
       "fortune_url": "/fortunes",
       "update_url": "/update?queries=",
-      "plaintext_url": "/plaintext",
       "port": 8080,
       "approach": "Realistic",
       "classification": "Fullstack",
@@ -20,9 +37,30 @@
       "webserver": "Resin",
       "os": "Linux",
       "database_os": "Linux",
-      "display_name": "gemini",
+      "display_name": "gemini-mysql",
+      "notes": "",
+      "versus": "servlet"
+    },
+    "postgres": {
+      "setup_file": "start_postgres",
+      "db_url": "/db",
+      "query_url": "/query?queries=",
+      "fortune_url": "/fortunes",
+      "update_url": "/update?queries=",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "Postgres",
+      "framework": "gemini",
+      "language": "Java",
+      "orm": "Micro",
+      "platform": "Servlet",
+      "webserver": "Resin",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "gemini-postgres",
       "notes": "",
       "versus": "servlet"
-    }
+    }   
   }]
 }

+ 1 - 0
frameworks/Java/gemini/source_code

@@ -24,6 +24,7 @@
 ./gemini/Docroot/WEB-INF/lib
 ./gemini/Docroot/WEB-INF/lib/kryonet-1.04-all.jar
 ./gemini/Docroot/WEB-INF/lib/mysql-connector-java-5.1.23-bin.jar
+./gemini-Docroot/WEB-INF/lib/postgresql-9.4-1200.jdbc41.jar
 ./gemini/Docroot/WEB-INF/lib/mustache-compiler-0.8.13.jar
 ./gemini/Docroot/WEB-INF/lib/mail.jar
 ./gemini/Docroot/WEB-INF/lib/activation.jar

+ 4 - 2
frameworks/Java/gemini/start.sh

@@ -1,7 +1,9 @@
 #!/bin/bash
 
-sed -i 's/db.ConnectString = .*:3306/db.ConnectString = '"$DBHOST"':3306/g' Docroot/WEB-INF/GeminiHello.conf
+sed -i 's|db.ConnectString = .*/|db.ConnectString = '"$DBHOST"':3306/|g' Docroot/WEB-INF/GeminiHello.conf
 sed -i 's|root-directory=".*/FrameworkBenchmarks/frameworks/Java/gemini|root-directory="'"$TROOT"'|g' Docroot/WEB-INF/resin.xml
+sed -i 's|db.Driver.Class = .*|db.Driver.Class = com.mysql.jdbc.Driver|g' Docroot/WEB-INF/GeminiHello.conf
+sed -i 's|db.Driver.UrlPrefix = .*|db.Driver.UrlPrefix = jdbc:mysql://|g' Docroot/WEB-INF/GeminiHello.conf
 mkdir -p Docroot/WEB-INF/classes
 ant compile
-$RESIN_HOME/bin/resinctl -conf $TROOT/Docroot/WEB-INF/resin.xml start
+$RESIN_HOME/bin/resinctl -conf $TROOT/Docroot/WEB-INF/resin.xml start

+ 9 - 0
frameworks/Java/gemini/start_postgres.sh

@@ -0,0 +1,9 @@
+#!/bin/bash
+
+sed -i 's|db.ConnectString = .*/|db.ConnectString = '"$DBHOST"':5432/|g' Docroot/WEB-INF/GeminiHello.conf
+sed -i 's|root-directory=".*/FrameworkBenchmarks/frameworks/Java/gemini|root-directory="'"$TROOT"'|g' Docroot/WEB-INF/resin.xml
+sed -i 's|db.Driver.Class = .*|db.Driver.Class = org.postgresql.Driver|g' Docroot/WEB-INF/GeminiHello.conf
+sed -i 's|db.Driver.UrlPrefix = .*|db.Driver.UrlPrefix = jdbc:postgresql://|g' Docroot/WEB-INF/GeminiHello.conf
+mkdir -p Docroot/WEB-INF/classes
+ant compile
+$RESIN_HOME/bin/resinctl -conf $TROOT/Docroot/WEB-INF/resin.xml start

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

@@ -8,17 +8,17 @@
 	<version>0.1</version>
 
 	<packaging>jar</packaging>
-
+	
 	<dependencies>
 		<dependency>
 			<groupId>io.netty</groupId>
 			<artifactId>netty-codec-http</artifactId>
-			<version>4.0.25.Final</version>
+			<version>4.0.26.Final</version>
 		</dependency>
 		<dependency>
 			<groupId>io.netty</groupId>
 			<artifactId>netty-transport-native-epoll</artifactId>
-			<version>4.0.25.Final</version>
+			<version>4.0.26.Final</version>
 			<classifier>linux-x86_64</classifier>
 		</dependency>
 		<dependency>

+ 8 - 1
frameworks/Java/netty/src/main/java/hello/HelloWebServer.java

@@ -1,5 +1,7 @@
 package hello;
 
+import java.net.InetSocketAddress;
+
 import io.netty.bootstrap.ServerBootstrap;
 import io.netty.buffer.PooledByteBufAllocator;
 import io.netty.channel.Channel;
@@ -38,6 +40,8 @@ public class HelloWebServer {
 
     private void doRun(EventLoopGroup loupGroup, Class<? extends ServerChannel> serverChannelClass) throws InterruptedException {
 	try {
+		InetSocketAddress inet = new InetSocketAddress(port);
+		
 	    ServerBootstrap b = new ServerBootstrap();
 	    b.option(ChannelOption.SO_BACKLOG, 1024);
 	    b.option(ChannelOption.SO_REUSEADDR, true);
@@ -47,7 +51,10 @@ public class HelloWebServer {
 	    b.childOption(ChannelOption.SO_REUSEADDR, true);
 	    b.childOption(ChannelOption.MAX_MESSAGES_PER_READ, Integer.MAX_VALUE);
 
-	    Channel ch = b.bind(port).sync().channel();
+	    Channel ch = b.bind(inet).sync().channel();
+	    
+	    System.out.printf("Httpd started. Listening on: %s%n", inet.toString());	    
+	    
 	    ch.closeFuture().sync();
 	} finally {
 	    loupGroup.shutdownGracefully().sync();

+ 1 - 1
frameworks/Java/ninja-standalone/pom.xml

@@ -9,7 +9,7 @@
 
     <properties>
         <java-version>1.7</java-version>
-        <ninja.version>4.0.0</ninja.version>
+        <ninja.version>4.0.5</ninja.version>
         <mysql.version>5.1.26</mysql.version>
         <jetty.version>9.2.1.v20140609</jetty.version>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

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

@@ -1,5 +1,12 @@
 #!/bin/bash
 
 cd play2-java
+
+# If application is running, clear old running app.
+if [ -f ${TROOT}/play2-java/target/universal/stage/RUNNING_PID ]
+then
+  rm -f -r ${TROOT}/play2-java/target/universal/stage/RUNNING_PID
+fi
+
 ${IROOT}/sbt/bin/sbt stage
-target/universal/stage/bin/play2-java &
+target/universal/stage/bin/play2-java &

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

@@ -1,5 +1,12 @@
 #!/bin/bash
 
 cd play2-java-ebean-bonecp
+
+# If application is running, clear old running app.
+if [ -f ${TROOT}/play2-java-ebean-bonecp/target/universal/stage/RUNNING_PID ]
+then
+  rm -f -r ${TROOT}/play2-java-ebean-bonecp/target/universal/stage/RUNNING_PID
+fi
+
 ${IROOT}/sbt/bin/sbt stage
-target/universal/stage/bin/play2-java-ebean-bonecp &
+target/universal/stage/bin/play2-java-ebean-bonecp &

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

@@ -1,5 +1,12 @@
 #!/bin/bash
 
 cd play2-java-ebean-hikaricp
+
+# If application is running, clear old running app.
+if [ -f ${TROOT}/play2-java-ebean-hikaricp/target/universal/stage/RUNNING_PID ]
+then
+  rm -f -r ${TROOT}/play2-java-ebean-hikaricp/target/universal/stage/RUNNING_PID
+fi
+
 ${IROOT}/sbt/bin/sbt stage
-target/universal/stage/bin/play2-java-ebean-hikaricp &
+target/universal/stage/bin/play2-java-ebean-hikaricp &

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

@@ -1,5 +1,12 @@
 #!/bin/bash
 
 cd play2-java-jpa-bonecp
+
+# If application is running, clear old running app.
+if [ -f ${TROOT}/play2-java-jpa-bonecp/target/universal/stage/RUNNING_PID ]
+then
+  rm -f -r ${TROOT}/play2-java-jpa-bonecp/target/universal/stage/RUNNING_PID
+fi
+
 ${IROOT}/sbt/bin/sbt stage
-target/universal/stage/bin/play2-java-jpa-bonecp &
+target/universal/stage/bin/play2-java-jpa-bonecp &

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

@@ -1,5 +1,12 @@
 #!/bin/bash
 
 cd play2-java-jpa-hikaricp
+
+# If application is running, clear old running app.
+if [ -f ${TROOT}/play2-java-jpa-hikaricp/target/universal/stage/RUNNING_PID ]
+then
+  rm -f -r ${TROOT}/play2-java-jpa-hikaricp/target/universal/stage/RUNNING_PID
+fi
+
 ${IROOT}/sbt/bin/sbt stage
-target/universal/stage/bin/play2-java-jpa-hikaricp &
+target/universal/stage/bin/play2-java-jpa-hikaricp &

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

@@ -0,0 +1,3 @@
+#@IgnoreInspection AddShebang
+
+export JAVA_HOME=/opt/java8

+ 10 - 8
frameworks/PHP/php-silica/benchmark_config → frameworks/Java/sabina/benchmark_config

@@ -1,24 +1,26 @@
 {
-  "framework": "silica",
+  "framework": "sabina",
   "tests": [{
-    "raw": {
+    "default": {
       "setup_file": "setup",
+      "json_url": "/json",
       "db_url": "/db",
       "query_url": "/db?queries=",
+      "plaintext_url": "/plaintext",
       "port": 8080,
       "approach": "Realistic",
       "classification": "Micro",
       "database": "MySQL",
-      "framework": "silica",
-      "language": "PHP",
+      "framework": "sabina",
+      "language": "Java",
       "orm": "Raw",
-      "platform": "PHP-FPM",
-      "webserver": "nginx",
+      "platform": "Servlet",
+      "webserver": "None",
       "os": "Linux",
       "database_os": "Linux",
-      "display_name": "silica",
+      "display_name": "Sabina",
       "notes": "",
-      "versus": "php"
+      "versus": "servlet"
     }
   }]
 }

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

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

+ 135 - 0
frameworks/Java/sabina/pom.xml

@@ -0,0 +1,135 @@
+<project
+    xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>sabina</groupId>
+    <artifactId>sabina</artifactId>
+    <version>1.0.0-SNAPSHOT</version>
+
+    <name>Sabina benchmark project</name>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+
+        <maven.compiler.source>${java.specification.version}</maven.compiler.source>
+        <maven.compiler.target>${java.specification.version}</maven.compiler.target>
+        <maven.compiler.optimize>true</maven.compiler.optimize>
+        <maven.compiler.debug>false</maven.compiler.debug>
+
+        <db.host>localhost</db.host>
+        <web.port>8080</web.port>
+
+        <sabina-version>1.0.0</sabina-version>
+        <mysql-connector-version>5.1.28</mysql-connector-version>
+    </properties>
+
+    <repositories>
+        <repository>
+            <snapshots>
+                <enabled>false</enabled>
+            </snapshots>
+            <id>central</id>
+            <name>bintray</name>
+            <url>http://jcenter.bintray.com</url>
+        </repository>
+    </repositories>
+    <pluginRepositories>
+        <pluginRepository>
+            <snapshots>
+                <enabled>false</enabled>
+            </snapshots>
+            <id>central</id>
+            <name>bintray-plugins</name>
+            <url>http://jcenter.bintray.com</url>
+        </pluginRepository>
+    </pluginRepositories>
+
+    <dependencies>
+        <dependency>
+            <groupId>sabina</groupId>
+            <artifactId>http</artifactId>
+            <version>${sabina-version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>javax.servlet</groupId>
+                    <artifactId>javax.servlet-api</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>sabina</groupId>
+            <artifactId>extra</artifactId>
+            <version>${sabina-version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.spec.javax.servlet</groupId>
+            <artifactId>jboss-servlet-api_3.1_spec</artifactId>
+            <version>1.0.0.Final</version>
+        </dependency>
+        <dependency>
+            <groupId>com.mchange</groupId>
+            <artifactId>c3p0</artifactId>
+            <version>0.9.2.1</version>
+        </dependency>
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <version>${mysql-connector-version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.11</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>fluent-hc</artifactId>
+            <version>4.4</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+                <filtering>true</filtering>
+            </resource>
+        </resources>
+
+        <plugins>
+            <plugin>
+                <artifactId>maven-shade-plugin</artifactId>
+                <version>2.3</version>
+                <configuration>
+                    <createDependencyReducedPom>false</createDependencyReducedPom>
+                </configuration>
+                <executions>
+                    <execution>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>shade</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <artifactId>maven-jar-plugin</artifactId>
+                <version>2.5</version>
+                <configuration>
+                    <archive>
+                        <manifest>
+                            <mainClass>sabina.benchmark.Application</mainClass>
+                        </manifest>
+                    </archive>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>

+ 44 - 0
frameworks/Java/sabina/readme.md

@@ -0,0 +1,44 @@
+
+# Sabina Benchmarking Test
+
+This is the Sabina portion of a [benchmarking test suite](../) comparing a variety of web
+development platforms. The test utilizes Sabina routes, Gson for JSON serialization and a custom
+OSIV pattern created with Sabina filters.
+
+
+## Tests
+
+* [Sabina application](/src/main/java/sabina/benchmark/Application.java)
+
+
+## Infrastructure Software Versions
+
+* [Sabina 1.0](http://there4.co/)
+
+
+## Different test setups
+
+* Local environment with Sabina's built in embedded Jetty (port=8080, context=/)
+ * Start application from [Application](/src/main/java/sabina/benchmark/Application.java)'s main method
+* Local environment with Sabina's built in embedded Undertow (port=8080, context=/)
+ * Start application from [Application](/src/main/java/sabina/benchmark/Application.java)'s main method
+
+
+## Test URLs
+
+### JSON Encoding Test
+
+http://localhost:8080/json
+
+### Data-Store/Database Mapping Test
+
+http://localhost:8080/db?queries=5
+
+### Plain Text Test
+
+http://localhost:8080/plaintext
+
+## TODO
+
+* Implement 'update' test
+* Implement 'fortunes' test

+ 4 - 0
frameworks/Java/sabina/setup.sh

@@ -0,0 +1,4 @@
+#!/bin/bash
+
+mvn clean package -Ddb.host=${DBHOST}
+${JAVA_HOME}/bin/java -jar target/sabina-1.0.0-SNAPSHOT.jar &

+ 4 - 0
frameworks/Java/sabina/source_code

@@ -0,0 +1,4 @@
+./sabina/src/main/java/
+./sabina/src/main/java/Application.java
+./sabina/src/main/java/Message.java
+./sabina/src/main/java/World.java

+ 141 - 0
frameworks/Java/sabina/src/main/java/sabina/benchmark/Application.java

@@ -0,0 +1,141 @@
+package sabina.benchmark;
+
+import static java.lang.Integer.parseInt;
+import static sabina.Sabina.*;
+import static sabina.content.JsonContent.toJson;
+
+import com.mchange.v2.c3p0.ComboPooledDataSource;
+import sabina.Exchange;
+import sabina.Request;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Date;
+import java.util.Properties;
+import java.util.Random;
+import java.util.concurrent.ThreadLocalRandom;
+
+import javax.sql.DataSource;
+
+/**
+ * When it is implemented, add this to benchmark_config
+ * "fortune_url": "/fortune",
+ * "update_url": "/update",
+ */
+final class Application {
+    private static final Properties CONFIG = loadConfig ();
+    private static final DataSource DS = createSessionFactory ();
+    private static final String QUERY = "select * from world where id = ?";
+
+    private static final int DB_ROWS = 10000;
+    private static final String MESSAGE = "Hello, World!";
+    private static final String CONTENT_TYPE_TEXT = "text/plain";
+
+    private static Properties loadConfig () {
+        try {
+            Properties config = new Properties ();
+            config.load (Class.class.getResourceAsStream ("/server.properties"));
+            return config;
+        }
+        catch (Exception ex) {
+            throw new RuntimeException (ex);
+        }
+    }
+
+    private static DataSource createSessionFactory () {
+        try {
+            ComboPooledDataSource cpds = new ComboPooledDataSource ();
+            cpds.setJdbcUrl (CONFIG.getProperty ("mysql.uri"));
+            cpds.setMinPoolSize (32);
+            cpds.setMaxPoolSize (256);
+            cpds.setCheckoutTimeout (1800);
+            cpds.setMaxStatements (50);
+            return cpds;
+        }
+        catch (Exception ex) {
+            throw new RuntimeException (ex);
+        }
+    }
+
+    private static int getQueries (final Request request) {
+        try {
+            String param = request.queryParams ("queries");
+            if (param == null)
+                return 1;
+
+            int queries = parseInt (param);
+            if (queries < 1)
+                return 1;
+            if (queries > 500)
+                return 500;
+
+            return queries;
+        }
+        catch (NumberFormatException ex) {
+            return 1;
+        }
+    }
+
+    private static Object getJson (Exchange it) {
+        it.response.type ("application/json");
+        return toJson (new Message ());
+    }
+
+    private static Object getDb (Exchange it) {
+        final int queries = getQueries (it.request);
+        final World[] worlds = new World[queries];
+
+        try (final Connection con = DS.getConnection ()) {
+            final Random random = ThreadLocalRandom.current ();
+            PreparedStatement stmt = con.prepareStatement (QUERY);
+
+            for (int i = 0; i < queries; i++) {
+                stmt.setInt (1, random.nextInt (DB_ROWS) + 1);
+                ResultSet rs = stmt.executeQuery ();
+                while (rs.next ()) {
+                    worlds[i] = new World ();
+                    worlds[i].id = rs.getInt (1);
+                    worlds[i].randomNumber = rs.getInt (2);
+                }
+            }
+        }
+        catch (SQLException e) {
+            e.printStackTrace ();
+        }
+
+        it.response.type ("application/json");
+        return toJson (it.request.queryParams ("queries") == null? worlds[0] : worlds);
+    }
+
+    private static Object getFortune (Exchange aExchange) {
+        throw new UnsupportedOperationException ();
+    }
+
+    private static Object getUpdate (Exchange aExchange) {
+        throw new UnsupportedOperationException ();
+    }
+
+    private static Object getPlaintext (Exchange it) {
+        it.response.type (CONTENT_TYPE_TEXT);
+        return MESSAGE;
+    }
+
+    private static void addCommonHeaders (Exchange it) {
+        it.header ("Server", "Undertow/1.1.2");
+        it.response.raw ().addDateHeader ("Date", new Date ().getTime ());
+    }
+
+    public static void main (String[] args) {
+        get ("/json", Application::getJson);
+        get ("/db", Application::getDb);
+        get ("/fortune", Application::getFortune);
+        get ("/update", Application::getUpdate);
+        get ("/plaintext", Application::getPlaintext);
+        after (Application::addCommonHeaders);
+
+        setIpAddress (CONFIG.getProperty ("web.host"));
+        start (parseInt (CONFIG.getProperty ("web.port")));
+    }
+}

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

@@ -0,0 +1,9 @@
+package sabina.benchmark;
+
+/**
+ * TODO .
+ *
+ * @author jam
+ */
+public class Fortune {
+}

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

@@ -0,0 +1,5 @@
+package sabina.benchmark;
+
+final class Message {
+    public final String message = "Hello, World!";
+}

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

@@ -0,0 +1,5 @@
+package sabina.benchmark;
+
+final class World {
+    public int id, randomNumber;
+}

+ 20 - 0
frameworks/Java/sabina/src/main/resources/sabina/view/fortunes.ftl

@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Fortunes</title>
+</head>
+<body>
+<table>
+    <tr>
+        <th>id</th>
+        <th>message</th>
+    </tr>
+    {{#.}}
+      <tr>
+          <td>{{id}}</td>
+          <td>{{message}}</td>
+      </tr>
+    {{/.}}
+</table>
+</body>
+</html>

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