Эх сурвалжийг харах

Submission of OfficeFloor (updated to remove tests and source_files) (#3895)

* Plain text test implemented

* Providing a test class per Tech Empower test

* Providing abstract class for generic testing

* Adding JSON serialise test

* Initial work on Single Database Query test

* Single Database Query test written.

* Multiple Database Queries Test

* Added Fortunes test

* All tests 1-6 written

* Json Serialisation requires JsonResponseWriter to specify the
Content-Type header.

* Single Query passing tests

* Multiple database queries passing

* Initial work on Fortunes test

* Fortunes test passing

* Passing unit tests

* Providing connection pooling and not logging.

* Providing threading configuration for database interaction

* Fixing issues with Database Update Test

* Tests are passing

* Setup of OfficeFloor to run in TechEmpire environment.

* Including production data source file

* Tests passing

* Tests now running in Vagrant VM

* Cleaning up start now that working.

* Should not have empty directory

* Plain text test implemented

* Providing a test class per Tech Empower test

* Providing abstract class for generic testing

* Adding JSON serialise test

* Initial work on Single Database Query test

* Single Database Query test written.

* Multiple Database Queries Test

* Added Fortunes test

* All tests 1-6 written

* Json Serialisation requires JsonResponseWriter to specify the
Content-Type header.

* Single Query passing tests

* Multiple database queries passing

* Initial work on Fortunes test

* Fortunes test passing

* Passing unit tests

* Providing connection pooling and not logging.

* Providing threading configuration for database interaction

* Fixing issues with Database Update Test

* Tests are passing

* Setup of OfficeFloor to run in TechEmpire environment.

* Including production data source file

* Tests passing

* Tests now running in Vagrant VM

* Cleaning up start now that working.

* Should not have empty directory

* Passing latest rebase of FrameworkBenchmarks.

* Migrating to version 3.0.0

* Run own comparison with just top level frameworks

* Fix file name spelling

* Providing readme placeholder for OfficeFloor

* Fixing for TTY not available in Jenkins

* Removing OfficeFloor to run setup script

* Initial setup

* Initial project setup

* OfficeFloor implementation passing tests

* Building OfficeFloor

* Fixing path

* Raw OfficeFloor

* Specifying SourceForge repository for sourcing

* Passing build - new SQL fix

* Able to be called for verify for officefloor-raw

* Adding Server / Date headers

* Configuring Postgresql

* Threading access to multiple queries on database

* Running all tests

* Fixing tests to pass verification

* re-useable tests for different implementations

* Pooling Connections

* Adding micro tests

* Providing micro, netty and rapidoid implementations

* Providing throttle active request count value

* Fixing spelling causing failed run

* Initial work to attempt to cache for local runs

* Fixing to start postgres for micro

* Improving Updates and Fortunes performance

* Reducing possible contention in database for updates

* Providing raw with DB functionality

* Including additional raw tests

* Including database for raw

* Fixing logic

* Ready for submission

* Ready for submission

* Cleaning up based on Tech Empower feedback:

 - Removing tests
 - Removing source_files
 - Also bumping up to use Java 10

* Removing test resources

* Fixing netty / rapidoid builds

Simplified build process to only build the project.  However, netty and
rapidoid depend on the benchmark default project for the implementation
(and just change the HTTP server).  Therefore, installing benchmark
first to allow the dependency to be resolved.

* Fixing for not finding parent pom

* Reverting back to Java 8

Issue with running with Java 10.  Will run in Java 8 for time being and
work on resolving this issue when more time.

* Increasing time for checking server up

Travis seems to run many builds at the same time, and concerned that may
be starving for thread to check causing timeout...  and subsequently
causing false positives.

* Working with Java 10

* Allowing to run on different port

CI server running on 8080 (so unable to start in unit tests)
Daniel 7 жил өмнө
parent
commit
cfd1a8644a
38 өөрчлөгдсөн 1482 нэмэгдсэн , 1 устгасан
  1. 1 0
      .travis.yml
  2. 40 0
      frameworks/Java/officefloor/README.md
  3. 117 0
      frameworks/Java/officefloor/benchmark_config.json
  4. BIN
      frameworks/Java/officefloor/configuration.png
  5. 10 0
      frameworks/Java/officefloor/officefloor-micro.dockerfile
  6. 14 0
      frameworks/Java/officefloor/officefloor-netty.dockerfile
  7. 14 0
      frameworks/Java/officefloor/officefloor-rapidoid.dockerfile
  8. 10 0
      frameworks/Java/officefloor/officefloor-raw.dockerfile
  9. 10 0
      frameworks/Java/officefloor/officefloor.dockerfile
  10. 1 0
      frameworks/Java/officefloor/src/.gitignore
  11. 151 0
      frameworks/Java/officefloor/src/pom.xml
  12. 99 0
      frameworks/Java/officefloor/src/woof_benchmark/pom.xml
  13. 26 0
      frameworks/Java/officefloor/src/woof_benchmark/src/main/java/net/officefloor/benchmark/Fortune.java
  14. 22 0
      frameworks/Java/officefloor/src/woof_benchmark/src/main/java/net/officefloor/benchmark/FortunesLogic.java
  15. 122 0
      frameworks/Java/officefloor/src/woof_benchmark/src/main/java/net/officefloor/benchmark/Logic.java
  16. 16 0
      frameworks/Java/officefloor/src/woof_benchmark/src/main/java/net/officefloor/benchmark/World.java
  17. 13 0
      frameworks/Java/officefloor/src/woof_benchmark/src/main/resources/META-INF/persistence.xml
  18. 12 0
      frameworks/Java/officefloor/src/woof_benchmark/src/main/resources/application.objects
  19. 5 0
      frameworks/Java/officefloor/src/woof_benchmark/src/main/resources/application.teams
  20. 44 0
      frameworks/Java/officefloor/src/woof_benchmark/src/main/resources/application.woof
  21. 6 0
      frameworks/Java/officefloor/src/woof_benchmark/src/main/resources/datasource.properties
  22. 1 0
      frameworks/Java/officefloor/src/woof_benchmark/src/main/resources/entitymanager.properties
  23. 1 0
      frameworks/Java/officefloor/src/woof_benchmark/src/main/resources/fortunes.html
  24. 1 0
      frameworks/Java/officefloor/src/woof_benchmark/src/main/resources/plaintext.html
  25. 66 0
      frameworks/Java/officefloor/src/woof_micro/pom.xml
  26. 24 0
      frameworks/Java/officefloor/src/woof_micro/src/main/java/net/officefloor/benchmark/Fortune.java
  27. 216 0
      frameworks/Java/officefloor/src/woof_micro/src/main/java/net/officefloor/benchmark/Logic.java
  28. 15 0
      frameworks/Java/officefloor/src/woof_micro/src/main/java/net/officefloor/benchmark/World.java
  29. 8 0
      frameworks/Java/officefloor/src/woof_micro/src/main/resources/application.objects
  30. 5 0
      frameworks/Java/officefloor/src/woof_micro/src/main/resources/application.teams
  31. 46 0
      frameworks/Java/officefloor/src/woof_micro/src/main/resources/application.woof
  32. 6 0
      frameworks/Java/officefloor/src/woof_micro/src/main/resources/datasource.properties
  33. 1 0
      frameworks/Java/officefloor/src/woof_micro/src/main/resources/plaintext.html
  34. 45 0
      frameworks/Java/officefloor/src/woof_netty/pom.xml
  35. 45 0
      frameworks/Java/officefloor/src/woof_rapidoid/pom.xml
  36. 54 0
      frameworks/Java/officefloor/src/woof_raw/pom.xml
  37. 213 0
      frameworks/Java/officefloor/src/woof_raw/src/main/java/net/officefloor/benchmark/RawOfficeFloorMain.java
  38. 2 1
      tfb

+ 1 - 0
.travis.yml

@@ -56,6 +56,7 @@ env:
      - "TESTDIR=Java/nanohttpd"
      - "TESTDIR=Java/netty"
      - "TESTDIR=Java/ninja-standalone"
+     - "TESTDIR=Java/officefloor"
      - "TESTDIR=Java/play1"
      - "TESTDIR=Java/play2-java"
      - "TESTDIR=Java/proteus"

+ 40 - 0
frameworks/Java/officefloor/README.md

@@ -0,0 +1,40 @@
+# OfficeFloor Benchmarking Test
+
+OfficeFloor is graphically configured through its true inversion of control.
+
+> Inversion of Control = Dependency Injection + Continuation Injection + Thread Injection
+
+More information can be found at [http://officefloor.net](http://officefloor.net)
+
+Further to this, graphical configuration is used.  The configuration is the following:
+
+![Graphical Configuration](configuration.png "OfficeFloor graphical configuration")
+
+The source code is:
+
+* [JSON, PLAINTEXT, DB, QUERY, UPDATE](src/woof_benchmark/src/main/java/net/officefloor/benchmark/Logic.java)
+* [FORTUNES](src/woof_benchmark/src/main/java/net/officefloor/benchmark/FortunesLogic.java)
+
+### JSON
+
+http://localhost:8080/json
+
+### PLAINTEXT
+
+http://localhost:8080/plaintext
+
+### DB
+
+http://localhost:8080/db
+
+### QUERY
+
+http://localhost:8080/query?queries=
+
+### UPDATE
+
+http://localhost:8080/update?queries=
+
+### FORTUNES
+
+http://localhost:8080/fortunes

+ 117 - 0
frameworks/Java/officefloor/benchmark_config.json

@@ -0,0 +1,117 @@
+{
+	"framework": "officefloor",
+	"tests": [
+		{
+			"default": {
+				"json_url": "/json",
+				"plaintext_url": "/plaintext",
+				"db_url": "/db",
+				"query_url": "/queries?queries=",
+				"fortune_url": "/fortunes",
+				"update_url": "/update?queries=",
+				"port": 8080,
+				"approach": "Realistic",
+				"classification": "Fullstack",
+				"database": "Postgres",
+				"framework": "OfficeFloor",
+				"language": "Java",
+				"flavor": "None",
+				"orm": "Full",
+				"platform": "OfficeFloor",
+				"webserver": "WoOF",
+				"os": "Linux",
+				"database_os": "Linux",
+				"display_name": "OfficeFloor",
+				"notes": "",
+				"versus": "officefloor-raw"
+			},
+			"raw": {
+				"json_url": "/json",
+				"plaintext_url": "/plaintext",
+				"port": 8080,
+				"approach": "Realistic",
+				"classification": "Platform",
+				"framework": "OfficeFloor",
+				"language": "Java",
+				"flavor": "None",
+				"orm": "raw",
+				"platform": "OfficeFloor",
+				"webserver": "WoOF",
+				"os": "Linux",
+				"database_os": "Linux",
+				"display_name": "OfficeFloor-raw",
+				"notes": "",
+				"versus": "None"
+			},
+			"micro": {
+				"json_url": "/json",
+				"plaintext_url": "/plaintext",
+				"db_url": "/db",
+				"query_url": "/queries?queries=",
+				"fortune_url": "/fortunes",
+				"update_url": "/update?queries=",
+				"port": 8080,
+				"approach": "Realistic",
+				"classification": "Fullstack",
+				"database": "Postgres",
+				"framework": "OfficeFloor",
+				"language": "Java",
+				"flavor": "None",
+				"orm": "raw",
+				"platform": "OfficeFloor",
+				"webserver": "WoOF",
+				"os": "Linux",
+				"database_os": "Linux",
+				"display_name": "OfficeFloor-micro",
+				"notes": "",
+				"versus": "OfficeFloor-raw"
+			},
+			"netty": {
+				"json_url": "/json",
+				"plaintext_url": "/plaintext",
+				"db_url": "/db",
+				"query_url": "/queries?queries=",
+				"fortune_url": "/fortunes",
+				"update_url": "/update?queries=",
+				"port": 8080,
+				"approach": "Realistic",
+				"classification": "Fullstack",
+				"database": "Postgres",
+				"framework": "OfficeFloor",
+				"language": "Java",
+				"flavor": "None",
+				"orm": "Full",
+				"platform": "OfficeFloor",
+				"webserver": "WoOF",
+				"os": "Linux",
+				"database_os": "Linux",
+				"display_name": "OfficeFloor-netty",
+				"notes": "",
+				"versus": "netty"
+			},
+			"rapidoid": {
+				"json_url": "/json",
+				"plaintext_url": "/plaintext",
+				"db_url": "/db",
+				"query_url": "/queries?queries=",
+				"fortune_url": "/fortunes",
+				"update_url": "/update?queries=",
+				"port": 8080,
+				"approach": "Realistic",
+				"classification": "Fullstack",
+				"database": "Postgres",
+				"framework": "OfficeFloor",
+				"language": "Java",
+				"flavor": "None",
+				"orm": "Full",
+				"platform": "OfficeFloor",
+				"webserver": "WoOF",
+				"os": "Linux",
+				"database_os": "Linux",
+				"display_name": "OfficeFloor-rapidoid",
+				"notes": "",
+				"versus": "rapidoid"
+			}
+		}
+	]
+}

BIN
frameworks/Java/officefloor/configuration.png


+ 10 - 0
frameworks/Java/officefloor/officefloor-micro.dockerfile

@@ -0,0 +1,10 @@
+FROM maven:3.5.4-jdk-10 as maven
+WORKDIR /officefloor
+COPY src src
+WORKDIR /officefloor/src/woof_micro
+RUN mvn clean package
+
+FROM openjdk:10
+WORKDIR /officefloor
+COPY --from=maven /officefloor/src/woof_micro/target/woof_micro-1.0.0.jar server.jar
+CMD ["java", "-server", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-XX:+AggressiveOpts", "-Dhttp.port=8080", "-Dhttp.server.name=OF", "-Dhttp.date.header=true", "-jar", "server.jar"]

+ 14 - 0
frameworks/Java/officefloor/officefloor-netty.dockerfile

@@ -0,0 +1,14 @@
+FROM maven:3.5.4-jdk-10 as maven
+WORKDIR /officefloor
+COPY src src
+WORKDIR /officefloor/src
+RUN mvn -N clean install
+WORKDIR /officefloor/src/woof_benchmark
+RUN mvn clean install
+WORKDIR /officefloor/src/woof_netty
+RUN mvn clean package
+
+FROM openjdk:10
+WORKDIR /officefloor
+COPY --from=maven /officefloor/src/woof_netty/target/woof_netty-1.0.0.jar server.jar
+CMD ["java", "-server", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-XX:+AggressiveOpts", "-Dhttp.port=8080", "-Dhttp.server.name=OF", "-Dhttp.date.header=true", "-jar", "server.jar"]

+ 14 - 0
frameworks/Java/officefloor/officefloor-rapidoid.dockerfile

@@ -0,0 +1,14 @@
+FROM maven:3.5.4-jdk-10 as maven
+WORKDIR /officefloor
+COPY src src
+WORKDIR /officefloor/src
+RUN mvn -N clean install
+WORKDIR /officefloor/src/woof_benchmark
+RUN mvn clean install
+WORKDIR /officefloor/src/woof_rapidoid
+RUN mvn clean package
+
+FROM openjdk:10
+WORKDIR /officefloor
+COPY --from=maven /officefloor/src/woof_rapidoid/target/woof_rapidoid-1.0.0.jar server.jar
+CMD ["java", "-server", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-XX:+AggressiveOpts", "-Dhttp.port=8080", "-Dhttp.server.name=OF", "-Dhttp.date.header=true", "-jar", "server.jar"]

+ 10 - 0
frameworks/Java/officefloor/officefloor-raw.dockerfile

@@ -0,0 +1,10 @@
+FROM maven:3.5.4-jdk-10 as maven
+WORKDIR /officefloor
+COPY src src
+WORKDIR /officefloor/src/woof_raw
+RUN mvn clean package
+
+FROM openjdk:10
+WORKDIR /officefloor
+COPY --from=maven /officefloor/src/woof_raw/target/woof_raw-1.0.0.jar server.jar
+CMD ["java", "-server", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-XX:+AggressiveOpts", "-jar", "server.jar"]

+ 10 - 0
frameworks/Java/officefloor/officefloor.dockerfile

@@ -0,0 +1,10 @@
+FROM maven:3.5.4-jdk-10 as maven
+WORKDIR /officefloor
+COPY src src
+WORKDIR /officefloor/src/woof_benchmark
+RUN mvn clean package
+
+FROM openjdk:10
+WORKDIR /officefloor
+COPY --from=maven /officefloor/src/woof_benchmark/target/woof_benchmark-1.0.0.jar server.jar
+CMD ["java", "-server", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-XX:+AggressiveOpts", "-Dhttp.port=8080", "-Dhttp.server.name=OF", "-Dhttp.date.header=true", "-jar", "server.jar"]

+ 1 - 0
frameworks/Java/officefloor/src/.gitignore

@@ -0,0 +1 @@
+/nexus.available

+ 151 - 0
frameworks/Java/officefloor/src/pom.xml

@@ -0,0 +1,151 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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>net.officefloor.benchmarks</groupId>
+	<artifactId>benchmarks</artifactId>
+	<version>1.0.0</version>
+	<packaging>pom</packaging>
+	<name>OfficeFloor Benchmarks</name>
+	<properties>
+		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+		<officefloor.version>3.0.0</officefloor.version>
+		<jackson.version>2.9.6</jackson.version>
+		<jaxb.version>2.3.0</jaxb.version>
+	</properties>
+	<modules>
+		<module>woof_benchmark</module>
+		<module>woof_micro</module>
+		<module>woof_raw</module>
+		<module>woof_netty</module>
+		<module>woof_rapidoid</module>
+	</modules>
+	<repositories>
+		<repository>
+			<id>maven2-repository.officefloor.net</id>
+			<name>OfficeFloor staging repository for Maven</name>
+			<url>http://www.officefloor.net/maven2/</url>
+		</repository>
+	</repositories>
+	<dependencyManagement>
+		<dependencies>
+			<dependency>
+				<groupId>net.officefloor.web</groupId>
+				<artifactId>woof</artifactId>
+				<version>${officefloor.version}</version>
+			</dependency>
+			<dependency>
+				<groupId>net.officefloor.server</groupId>
+				<artifactId>officeserver_netty</artifactId>
+				<version>${officefloor.version}</version>
+			</dependency>
+			<dependency>
+				<groupId>net.officefloor.server</groupId>
+				<artifactId>officeserver_rapidoid</artifactId>
+				<version>${officefloor.version}</version>
+			</dependency>
+			<dependency>
+				<groupId>net.officefloor.web</groupId>
+				<artifactId>officejson_jackson</artifactId>
+				<version>${officefloor.version}</version>
+			</dependency>
+			<dependency>
+				<groupId>com.fasterxml.jackson.core</groupId>
+				<artifactId>jackson-databind</artifactId>
+				<version>${jackson.version}</version>
+			</dependency>
+			<dependency>
+				<groupId>com.fasterxml.jackson.module</groupId>
+				<artifactId>jackson-module-afterburner</artifactId>
+				<version>${jackson.version}</version>
+			</dependency>
+			<dependency>
+				<groupId>net.officefloor.persistence</groupId>
+				<artifactId>officejpa</artifactId>
+				<version>${officefloor.version}</version>
+			</dependency>
+			<dependency>
+				<groupId>net.officefloor.persistence</groupId>
+				<artifactId>officejdbc</artifactId>
+				<version>${officefloor.version}</version>
+			</dependency>
+			<dependency>
+				<groupId>net.officefloor.persistence</groupId>
+				<artifactId>officejdbc_postgresql</artifactId>
+				<version>${officefloor.version}</version>
+			</dependency>
+			<dependency>
+				<groupId>net.officefloor.persistence</groupId>
+				<artifactId>officejpa_hibernate</artifactId>
+				<version>${officefloor.version}</version>
+			</dependency>
+			<dependency>
+				<groupId>org.hibernate</groupId>
+				<artifactId>hibernate-core</artifactId>
+				<version>5.3.1.Final</version>
+			</dependency>
+			<dependency>
+				<groupId>javax.xml.bind</groupId>
+				<artifactId>jaxb-api</artifactId>
+				<version>${jaxb.version}</version>
+			</dependency>
+			<dependency>
+				<groupId>com.sun.xml.bind</groupId>
+				<artifactId>jaxb-core</artifactId>
+				<version>${jaxb.version}</version>
+			</dependency>
+			<dependency>
+				<groupId>com.sun.xml.bind</groupId>
+				<artifactId>jaxb-impl</artifactId>
+				<version>${jaxb.version}</version>
+			</dependency>
+			<dependency>
+				<groupId>javax.activation</groupId>
+				<artifactId>javax.activation-api</artifactId>
+				<version>1.2.0</version>
+			</dependency>
+			<dependency>
+				<groupId>javax.transaction</groupId>
+				<artifactId>javax.transaction-api</artifactId>
+				<version>1.3</version>
+			</dependency>
+			<dependency>
+				<groupId>org.postgresql</groupId>
+				<artifactId>postgresql</artifactId>
+				<version>42.2.2</version>
+			</dependency>
+			<dependency>
+				<groupId>org.projectlombok</groupId>
+				<artifactId>lombok</artifactId>
+				<version>1.18.0</version>
+			</dependency>
+			<dependency>
+				<groupId>net.officefloor.benchmarks</groupId>
+				<artifactId>woof_benchmark</artifactId>
+				<version>${project.version}</version>
+			</dependency>
+		</dependencies>
+	</dependencyManagement>
+	<build>
+		<pluginManagement>
+			<plugins>
+				<plugin>
+					<groupId>org.apache.maven.plugins</groupId>
+					<artifactId>maven-compiler-plugin</artifactId>
+					<version>3.7.0</version>
+					<configuration>
+						<source>8</source>
+						<target>8</target>
+						<optimize>true</optimize>
+						<debug>false</debug>
+					</configuration>
+				</plugin>
+				<plugin>
+					<groupId>org.apache.maven.plugins</groupId>
+					<artifactId>maven-shade-plugin</artifactId>
+					<version>3.1.1</version>
+				</plugin>
+			</plugins>
+		</pluginManagement>
+	</build>
+</project>

+ 99 - 0
frameworks/Java/officefloor/src/woof_benchmark/pom.xml

@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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>
+	<parent>
+		<groupId>net.officefloor.benchmarks</groupId>
+		<artifactId>benchmarks</artifactId>
+		<version>1.0.0</version>
+	</parent>
+	<artifactId>woof_benchmark</artifactId>
+	<dependencies>
+		<dependency>
+			<groupId>net.officefloor.web</groupId>
+			<artifactId>woof</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>net.officefloor.web</groupId>
+			<artifactId>officejson_jackson</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>com.fasterxml.jackson.core</groupId>
+			<artifactId>jackson-databind</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>com.fasterxml.jackson.module</groupId>
+			<artifactId>jackson-module-afterburner</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>net.officefloor.persistence</groupId>
+			<artifactId>officejpa</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>net.officefloor.persistence</groupId>
+			<artifactId>officejpa_hibernate</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.hibernate</groupId>
+			<artifactId>hibernate-core</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>javax.xml.bind</groupId>
+			<artifactId>jaxb-api</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>com.sun.xml.bind</groupId>
+			<artifactId>jaxb-core</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>com.sun.xml.bind</groupId>
+			<artifactId>jaxb-impl</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>javax.activation</groupId>
+			<artifactId>javax.activation-api</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>javax.transaction</groupId>
+			<artifactId>javax.transaction-api</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>net.officefloor.persistence</groupId>
+			<artifactId>officejdbc_postgresql</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.postgresql</groupId>
+			<artifactId>postgresql</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.projectlombok</groupId>
+			<artifactId>lombok</artifactId>
+			<scope>provided</scope>
+		</dependency>
+	</dependencies>
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-shade-plugin</artifactId>
+				<executions>
+					<execution>
+						<phase>package</phase>
+						<goals>
+							<goal>shade</goal>
+						</goals>
+						<configuration>
+							<transformers>
+								<transformer
+									implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+									<mainClass>net.officefloor.OfficeFloorMain</mainClass>
+								</transformer>
+							</transformers>
+						</configuration>
+					</execution>
+				</executions>
+			</plugin>
+		</plugins>
+	</build>
+</project>

+ 26 - 0
frameworks/Java/officefloor/src/woof_benchmark/src/main/java/net/officefloor/benchmark/Fortune.java

@@ -0,0 +1,26 @@
+package net.officefloor.benchmark;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.NamedQuery;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Entity
+@NamedQuery(name = "All", query = "SELECT f FROM Fortune f")
+public class Fortune {
+
+	@Id
+	private int id;
+
+	private String message;
+	
+	public String getMessage() {
+		return this.message;
+	}
+}

+ 22 - 0
frameworks/Java/officefloor/src/woof_benchmark/src/main/java/net/officefloor/benchmark/FortunesLogic.java

@@ -0,0 +1,22 @@
+package net.officefloor.benchmark;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+
+/**
+ * Fortunes logic.
+ */
+public class FortunesLogic {
+
+	public Fortune[] getFortunes(EntityManager entityManager) {
+		List<Fortune> fortunes = new ArrayList<>();
+		entityManager.createNamedQuery("All", Fortune.class).getResultStream()
+				.forEach((fortune) -> fortunes.add(fortune));
+		fortunes.add(new Fortune(0, "Additional fortune added at request time."));
+		fortunes.sort((a, b) -> a.getMessage().compareTo(b.getMessage()));
+		return fortunes.toArray(new Fortune[fortunes.size()]);
+	}
+
+}

+ 122 - 0
frameworks/Java/officefloor/src/woof_benchmark/src/main/java/net/officefloor/benchmark/Logic.java

@@ -0,0 +1,122 @@
+package net.officefloor.benchmark;
+
+import java.util.concurrent.ThreadLocalRandom;
+
+import javax.persistence.EntityManager;
+
+import lombok.Data;
+import net.officefloor.frame.api.function.FlowCallback;
+import net.officefloor.plugin.managedfunction.clazz.FlowInterface;
+import net.officefloor.plugin.section.clazz.Parameter;
+import net.officefloor.plugin.section.clazz.Spawn;
+import net.officefloor.web.HttpQueryParameter;
+import net.officefloor.web.ObjectResponse;
+
+/**
+ * Logic.
+ */
+public class Logic {
+
+	// =========== JSON ===================
+
+	@Data
+	public static class Message {
+		private final String message;
+	}
+
+	public void json(ObjectResponse<Message> response) {
+		response.send(new Message("Hello, World!"));
+	}
+
+	// ============ DB ====================
+
+	public void db(EntityManager entityManager, ObjectResponse<World> response) {
+		response.send(entityManager.find(World.class, ThreadLocalRandom.current().nextInt(1, 10000)));
+	}
+
+	// ========== QUERIES ==================
+
+	public void queries(@HttpQueryParameter("queries") String queries, QueriesFlows flows,
+			ObjectResponse<World[]> response) {
+		ThreadLocalRandom random = ThreadLocalRandom.current();
+		int[] loaded = new int[] { 0 };
+		int count = getQueryCount(queries);
+		World[] worlds = new World[count];
+		for (int i = 0; i < worlds.length; i++) {
+			int index = i;
+			GetEntry entry = new GetEntry(random.nextInt(1, 10000));
+			flows.getEntry(entry, (escalation) -> {
+				worlds[index] = entry.world;
+				loaded[0]++;
+				if (loaded[0] >= count) {
+					response.send(worlds);
+				}
+			});
+		}
+	}
+
+	@Data
+	public static class GetEntry {
+		private final int id;
+		private World world;
+	}
+
+	@FlowInterface
+	public static interface QueriesFlows {
+		@Spawn
+		void getEntry(GetEntry entry, FlowCallback callback);
+	}
+
+	public void getEntry(@Parameter GetEntry entry, EntityManager entityManager) {
+		entry.world = entityManager.find(World.class, entry.id);
+	}
+
+	// =========== UPDATES ===================
+
+	public void update(@HttpQueryParameter("queries") String queries, UpdatesFlows flows,
+			ObjectResponse<World[]> response) {
+		int[] loaded = new int[] { 0 };
+		int count = getQueryCount(queries);
+		World[] worlds = new World[count];
+		for (int i = 0; i < worlds.length; i++) {
+			int index = i;
+			UpdateEntry entry = new UpdateEntry();
+			flows.updateEntry(entry, (escalation) -> {
+				worlds[index] = entry.world;
+				loaded[0]++;
+				if (loaded[0] >= count) {
+					response.send(worlds);
+				}
+			});
+		}
+	}
+
+	@FlowInterface
+	public static interface UpdatesFlows {
+		@Spawn
+		void updateEntry(UpdateEntry entry, FlowCallback callback);
+	}
+
+	@Data
+	public static class UpdateEntry {
+		private World world;
+	}
+
+	public void updateEntry(@Parameter UpdateEntry entry, EntityManager entityManager) {
+		ThreadLocalRandom random = ThreadLocalRandom.current();
+		entry.world = entityManager.find(World.class, random.nextInt(1, 10000));
+		entry.world.setRandomNumber(random.nextInt(1, 10000));
+	}
+
+	// =========== helper ===================
+
+	private static int getQueryCount(String queries) {
+		try {
+			int count = Integer.parseInt(queries);
+			return (count < 1) ? 1 : (count > 500) ? 500 : count;
+		} catch (NumberFormatException ex) {
+			return 1;
+		}
+	}
+
+}

+ 16 - 0
frameworks/Java/officefloor/src/woof_benchmark/src/main/java/net/officefloor/benchmark/World.java

@@ -0,0 +1,16 @@
+package net.officefloor.benchmark;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+
+import lombok.Data;
+
+@Data
+@Entity
+public class World {
+
+	@Id
+	private int id;
+
+	private int randomNumber;
+}

+ 13 - 0
frameworks/Java/officefloor/src/woof_benchmark/src/main/resources/META-INF/persistence.xml

@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<persistence xmlns="http://java.sun.com/xml/ns/persistence"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
+	version="2.0">
+
+	<persistence-unit name="benchmarks">
+		<class>net.officefloor.benchmark.World</class>
+		<class>net.officefloor.benchmark.Fortune</class>
+		<exclude-unlisted-classes />
+	</persistence-unit>
+
+</persistence>

+ 12 - 0
frameworks/Java/officefloor/src/woof_benchmark/src/main/resources/application.objects

@@ -0,0 +1,12 @@
+<objects>
+
+	<managed-object source="net.officefloor.jdbc.ConnectionManagedObjectSource" type="java.sql.Connection">
+		<property-file path="datasource.properties" />
+		<pool source="net.officefloor.jdbc.pool.ThreadLocalJdbcConnectionPoolSource" />
+	</managed-object>
+
+	<managed-object source="net.officefloor.jpa.hibernate.HibernateJpaManagedObjectSource" type="javax.persistence.EntityManager">
+		<property-file path="entitymanager.properties" />
+	</managed-object>
+
+</objects>

+ 5 - 0
frameworks/Java/officefloor/src/woof_benchmark/src/main/resources/application.teams

@@ -0,0 +1,5 @@
+<teams>
+
+	<team source="net.officefloor.frame.impl.spi.team.ExecutorCachedTeamSource" type="java.sql.Connection" />
+
+</teams>

+ 44 - 0
frameworks/Java/officefloor/src/woof_benchmark/src/main/resources/application.woof

@@ -0,0 +1,44 @@
+<woof>
+  <http-continuations>
+    <http-continuation path="/db" secure="false" x="87" y="172">
+      <section name="Logic" input="db"/>
+    </http-continuation>
+    <http-continuation path="/json" secure="false" x="84" y="123">
+      <section name="Logic" input="json"/>
+    </http-continuation>
+    <http-continuation path="/queries" secure="false" x="80" y="222">
+      <section name="Logic" input="queries"/>
+    </http-continuation>
+    <http-continuation path="/update" secure="false" x="80" y="275">
+      <section name="Logic" input="update"/>
+    </http-continuation>
+  </http-continuations>
+  <http-inputs>
+  </http-inputs>
+  <templates>
+    <template path="/fortunes" location="fortunes.html" class="net.officefloor.benchmark.FortunesLogic" content-type="text/html;charset=utf-8" charset="" secure="false" redirect-values-function="" link-separator-character="" x="276" y="44">
+    </template>
+    <template path="/plaintext" location="plaintext.html" class="" content-type="text/plain" charset="" secure="false" redirect-values-function="" link-separator-character="" x="64" y="46">
+    </template>
+  </templates>
+  <sections>
+    <section name="Logic" source="net.officefloor.plugin.section.clazz.ClassSectionSource" location="net.officefloor.benchmark.Logic" x="281" y="140">
+      <input name="db" parameter-type=""/>
+      <input name="getEntry" parameter-type="net.officefloor.benchmark.Logic$GetEntry"/>
+      <input name="json" parameter-type=""/>
+      <input name="queries" parameter-type=""/>
+      <input name="update" parameter-type=""/>
+      <input name="updateEntry" parameter-type="net.officefloor.benchmark.Logic$UpdateEntry"/>
+    </section>
+  </sections>
+  <securities>
+  </securities>
+  <governances>
+  </governances>
+  <resources>
+  </resources>
+  <exceptions>
+  </exceptions>
+  <starting>
+  </starting>
+</woof>

+ 6 - 0
frameworks/Java/officefloor/src/woof_benchmark/src/main/resources/datasource.properties

@@ -0,0 +1,6 @@
+datasource.factory=net.officefloor.jdbc.postgresql.PostgreSqlConnectionManagedObjectSource
+server=tfb-database
+port=5432
+database=hello_world
+user=benchmarkdbuser
+password=benchmarkdbpass

+ 1 - 0
frameworks/Java/officefloor/src/woof_benchmark/src/main/resources/entitymanager.properties

@@ -0,0 +1 @@
+persistence.unit.name=benchmarks

+ 1 - 0
frameworks/Java/officefloor/src/woof_benchmark/src/main/resources/fortunes.html

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

+ 1 - 0
frameworks/Java/officefloor/src/woof_benchmark/src/main/resources/plaintext.html

@@ -0,0 +1 @@
+Hello, World!

+ 66 - 0
frameworks/Java/officefloor/src/woof_micro/pom.xml

@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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>
+	<parent>
+		<groupId>net.officefloor.benchmarks</groupId>
+		<artifactId>benchmarks</artifactId>
+		<version>1.0.0</version>
+	</parent>
+	<artifactId>woof_micro</artifactId>
+	<dependencies>
+		<dependency>
+			<groupId>net.officefloor.web</groupId>
+			<artifactId>woof</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>net.officefloor.web</groupId>
+			<artifactId>officejson_jackson</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>com.fasterxml.jackson.core</groupId>
+			<artifactId>jackson-databind</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>com.fasterxml.jackson.module</groupId>
+			<artifactId>jackson-module-afterburner</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>net.officefloor.persistence</groupId>
+			<artifactId>officejdbc_postgresql</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.postgresql</groupId>
+			<artifactId>postgresql</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.projectlombok</groupId>
+			<artifactId>lombok</artifactId>
+			<scope>provided</scope>
+		</dependency>
+	</dependencies>
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-shade-plugin</artifactId>
+				<executions>
+					<execution>
+						<phase>package</phase>
+						<goals>
+							<goal>shade</goal>
+						</goals>
+						<configuration>
+							<transformers>
+								<transformer
+									implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+									<mainClass>net.officefloor.OfficeFloorMain</mainClass>
+								</transformer>
+							</transformers>
+						</configuration>
+					</execution>
+				</executions>
+			</plugin>
+		</plugins>
+	</build>
+</project>

+ 24 - 0
frameworks/Java/officefloor/src/woof_micro/src/main/java/net/officefloor/benchmark/Fortune.java

@@ -0,0 +1,24 @@
+package net.officefloor.benchmark;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class Fortune implements Comparable<Fortune> {
+
+	private int id;
+
+	private String message;
+
+	public String getMessage() {
+		return this.message;
+	}
+
+	@Override
+	public int compareTo(Fortune o) {
+		return this.getMessage().compareTo(o.getMessage());
+	}
+}

+ 216 - 0
frameworks/Java/officefloor/src/woof_micro/src/main/java/net/officefloor/benchmark/Logic.java

@@ -0,0 +1,216 @@
+package net.officefloor.benchmark;
+
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ThreadLocalRandom;
+
+import org.apache.commons.text.StringEscapeUtils;
+
+import lombok.Data;
+import net.officefloor.frame.api.function.FlowCallback;
+import net.officefloor.plugin.managedfunction.clazz.FlowInterface;
+import net.officefloor.plugin.section.clazz.Parameter;
+import net.officefloor.plugin.section.clazz.Spawn;
+import net.officefloor.server.http.HttpHeaderValue;
+import net.officefloor.server.http.HttpResponse;
+import net.officefloor.server.http.ServerHttpConnection;
+import net.officefloor.server.stream.ServerWriter;
+import net.officefloor.web.HttpQueryParameter;
+import net.officefloor.web.ObjectResponse;
+
+/**
+ * Logic.
+ */
+public class Logic {
+
+	// =========== JSON ===================
+
+	@Data
+	public static class Message {
+		private final String message;
+	}
+
+	public void json(ObjectResponse<Message> response) {
+		response.send(new Message("Hello, World!"));
+	}
+
+	// ============ DB ====================
+
+	public void db(Connection connection, ObjectResponse<World> response) throws SQLException {
+		try (PreparedStatement statement = connection.prepareStatement(
+				"SELECT ID, RANDOMNUMBER FROM WORLD WHERE ID = ?", ResultSet.TYPE_FORWARD_ONLY,
+				ResultSet.CONCUR_READ_ONLY)) {
+			statement.setInt(1, ThreadLocalRandom.current().nextInt(1, 10000));
+			ResultSet resultSet = statement.executeQuery();
+			resultSet.next();
+			World world = new World(resultSet.getInt(1), resultSet.getInt(2));
+			response.send(world);
+		}
+	}
+
+	// ========== QUERIES ==================
+
+	public void queries(@HttpQueryParameter("queries") String queries, QueriesFlows flows,
+			ObjectResponse<World[]> response) {
+		ThreadLocalRandom random = ThreadLocalRandom.current();
+		int[] loaded = new int[] { 0 };
+		int count = getQueryCount(queries);
+		World[] worlds = new World[count];
+		for (int i = 0; i < worlds.length; i++) {
+			int index = i;
+			GetEntry entry = new GetEntry(random.nextInt(1, 10000));
+			flows.getEntry(entry, (escalation) -> {
+				worlds[index] = entry.world;
+				loaded[0]++;
+				if (loaded[0] >= count) {
+					response.send(worlds);
+				}
+			});
+		}
+	}
+
+	@Data
+	public static class GetEntry {
+		private final int id;
+		private World world;
+	}
+
+	@FlowInterface
+	public static interface QueriesFlows {
+		@Spawn
+		void getEntry(GetEntry entry, FlowCallback callback);
+	}
+
+	public void getEntry(@Parameter GetEntry entry, Connection connection) throws SQLException {
+		try (PreparedStatement statement = connection.prepareStatement(
+				"SELECT ID, RANDOMNUMBER FROM WORLD WHERE ID = ?", ResultSet.TYPE_FORWARD_ONLY,
+				ResultSet.CONCUR_READ_ONLY)) {
+			statement.setInt(1, entry.id);
+			ResultSet resultSet = statement.executeQuery();
+			resultSet.next();
+			entry.world = new World(resultSet.getInt(1), resultSet.getInt(2));
+		}
+	}
+
+	// =========== UPDATES ===================
+
+	public void update(@HttpQueryParameter("queries") String queries, UpdatesFlows flows) {
+		ThreadLocalRandom random = ThreadLocalRandom.current();
+		int[] loaded = new int[] { 0 };
+		int count = getQueryCount(queries);
+		World[] worlds = new World[count];
+		for (int i = 0; i < worlds.length; i++) {
+			int index = i;
+			UpdateEntry entry = new UpdateEntry(random.nextInt(1, 10000));
+			flows.updateEntry(entry, (escalation) -> {
+				worlds[index] = entry.world;
+				loaded[0]++;
+				if (loaded[0] >= count) {
+					flows.doUpdates(worlds);
+				}
+			});
+		}
+	}
+
+	@FlowInterface
+	public static interface UpdatesFlows {
+		@Spawn
+		void updateEntry(UpdateEntry entry, FlowCallback callback);
+
+		void doUpdates(World[] worlds);
+	}
+
+	@Data
+	public static class UpdateEntry {
+		private final int id;
+		private World world;
+	}
+
+	public void updateEntry(@Parameter UpdateEntry entry, Connection connection) throws SQLException {
+		ThreadLocalRandom random = ThreadLocalRandom.current();
+		try (PreparedStatement statement = connection.prepareStatement("SELECT ID FROM WORLD WHERE ID = ?",
+				ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)) {
+			statement.setInt(1, entry.id);
+			ResultSet resultSet = statement.executeQuery();
+			resultSet.next();
+			entry.world = new World(resultSet.getInt(1), random.nextInt(1, 10000));
+		}
+	}
+
+	public void doUpdates(@Parameter World[] worlds, Connection connection, ObjectResponse<World[]> response)
+			throws SQLException {
+		Arrays.sort(worlds, (a, b) -> a.getId() - b.getId());
+		try (PreparedStatement statement = connection
+				.prepareStatement("UPDATE WORLD SET RANDOMNUMBER = ? WHERE ID = ?")) {
+			for (int u = 0; u < worlds.length; u++) {
+				statement.setInt(1, worlds[u].getRandomNumber());
+				statement.setInt(2, worlds[u].getId());
+				statement.addBatch();
+			}
+			statement.executeBatch();
+		}
+		response.send(worlds);
+	}
+
+	// =========== FORTUNES ==================
+
+	private static final HttpHeaderValue TEXT_HTML = new HttpHeaderValue("text/html;charset=utf-8");
+
+	private static final byte[] TEMPLATE_START = "<!DOCTYPE html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr>"
+			.getBytes(ServerHttpConnection.DEFAULT_HTTP_ENTITY_CHARSET);
+
+	private static final byte[] FORTUNE_START = "<tr><td>".getBytes(ServerHttpConnection.DEFAULT_HTTP_ENTITY_CHARSET);
+
+	private static final byte[] FORTUNE_MIDDLE = "</td><td>".getBytes(ServerHttpConnection.DEFAULT_HTTP_ENTITY_CHARSET);
+
+	private static final byte[] FORTUNE_END = "</td></tr>".getBytes(ServerHttpConnection.DEFAULT_HTTP_ENTITY_CHARSET);
+
+	private static final byte[] TEMPLATE_END = "</table></body></html>"
+			.getBytes(ServerHttpConnection.DEFAULT_HTTP_ENTITY_CHARSET);
+
+	public void fortunes(Connection connection, ServerHttpConnection httpConnection) throws IOException, SQLException {
+		try (PreparedStatement statement = connection.prepareStatement("SELECT ID, MESSAGE FROM FORTUNE",
+				ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)) {
+			List<Fortune> fortunes = new ArrayList<>();
+			fortunes.add(new Fortune(0, "Additional fortune added at request time."));
+			ResultSet resultSet = statement.executeQuery();
+			while (resultSet.next()) {
+				fortunes.add(new Fortune(resultSet.getInt(1), resultSet.getString(2)));
+			}
+			HttpResponse response = httpConnection.getResponse();
+			response.setContentType(TEXT_HTML, null);
+			ServerWriter writer = response.getEntityWriter();
+			writer.write(TEMPLATE_START);
+			Collections.sort(fortunes);
+			for (int i = 0; i < fortunes.size(); i++) {
+				Fortune fortune = fortunes.get(i);
+				writer.write(FORTUNE_START);
+				int id = fortune.getId();
+				writer.write(Integer.valueOf(id).toString());
+				writer.write(FORTUNE_MIDDLE);
+				StringEscapeUtils.ESCAPE_HTML4.translate(fortune.getMessage(), writer);
+				writer.write(FORTUNE_END);
+			}
+			writer.write(TEMPLATE_END);
+		}
+	}
+
+	// =========== helper ===================
+
+	private static int getQueryCount(String queries) {
+		try {
+			int count = Integer.parseInt(queries);
+			return (count < 1) ? 1 : (count > 500) ? 500 : count;
+		} catch (NumberFormatException ex) {
+			return 1;
+		}
+	}
+
+}

+ 15 - 0
frameworks/Java/officefloor/src/woof_micro/src/main/java/net/officefloor/benchmark/World.java

@@ -0,0 +1,15 @@
+package net.officefloor.benchmark;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class World {
+
+	private int id;
+
+	private int randomNumber;
+}

+ 8 - 0
frameworks/Java/officefloor/src/woof_micro/src/main/resources/application.objects

@@ -0,0 +1,8 @@
+<objects>
+
+	<managed-object source="net.officefloor.jdbc.ConnectionManagedObjectSource" type="java.sql.Connection">
+		<property-file path="datasource.properties" />
+		<pool source="net.officefloor.jdbc.pool.ThreadLocalJdbcConnectionPoolSource" />
+	</managed-object>
+
+</objects>

+ 5 - 0
frameworks/Java/officefloor/src/woof_micro/src/main/resources/application.teams

@@ -0,0 +1,5 @@
+<teams>
+
+	<team source="net.officefloor.frame.impl.spi.team.ExecutorCachedTeamSource" type="java.sql.Connection" />
+
+</teams>

+ 46 - 0
frameworks/Java/officefloor/src/woof_micro/src/main/resources/application.woof

@@ -0,0 +1,46 @@
+<woof>
+  <http-continuations>
+    <http-continuation path="/db" secure="false" x="87" y="172">
+      <section name="Logic" input="db"/>
+    </http-continuation>
+    <http-continuation path="/fortunes" secure="false" x="78" y="213">
+      <section name="Logic" input="fortunes"/>
+    </http-continuation>
+    <http-continuation path="/json" secure="false" x="84" y="123">
+      <section name="Logic" input="json"/>
+    </http-continuation>
+    <http-continuation path="/queries" secure="false" x="82" y="270">
+      <section name="Logic" input="queries"/>
+    </http-continuation>
+    <http-continuation path="/update" secure="false" x="82" y="323">
+      <section name="Logic" input="update"/>
+    </http-continuation>
+  </http-continuations>
+  <http-inputs>
+  </http-inputs>
+  <templates>
+    <template path="/plaintext" location="plaintext.html" class="" content-type="text/plain" charset="" secure="false" redirect-values-function="" link-separator-character="" x="64" y="46">
+    </template>
+  </templates>
+  <sections>
+    <section name="Logic" source="net.officefloor.plugin.section.clazz.ClassSectionSource" location="net.officefloor.benchmark.Logic" x="281" y="140">
+      <input name="db" parameter-type=""/>
+      <input name="fortunes" parameter-type=""/>
+      <input name="getEntry" parameter-type="net.officefloor.benchmark.Logic$GetEntry"/>
+      <input name="json" parameter-type=""/>
+      <input name="queries" parameter-type=""/>
+      <input name="update" parameter-type=""/>
+      <input name="updateEntry" parameter-type="net.officefloor.benchmark.Logic$UpdateEntry"/>
+    </section>
+  </sections>
+  <securities>
+  </securities>
+  <governances>
+  </governances>
+  <resources>
+  </resources>
+  <exceptions>
+  </exceptions>
+  <starting>
+  </starting>
+</woof>

+ 6 - 0
frameworks/Java/officefloor/src/woof_micro/src/main/resources/datasource.properties

@@ -0,0 +1,6 @@
+datasource.factory=net.officefloor.jdbc.postgresql.PostgreSqlConnectionManagedObjectSource
+server=tfb-database
+port=5432
+database=hello_world
+user=benchmarkdbuser
+password=benchmarkdbpass

+ 1 - 0
frameworks/Java/officefloor/src/woof_micro/src/main/resources/plaintext.html

@@ -0,0 +1 @@
+Hello, World!

+ 45 - 0
frameworks/Java/officefloor/src/woof_netty/pom.xml

@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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>
+	<parent>
+		<groupId>net.officefloor.benchmarks</groupId>
+		<artifactId>benchmarks</artifactId>
+		<version>1.0.0</version>
+	</parent>
+	<artifactId>woof_netty</artifactId>
+	<dependencies>
+		<dependency>
+			<groupId>net.officefloor.benchmarks</groupId>
+			<artifactId>woof_benchmark</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>net.officefloor.server</groupId>
+			<artifactId>officeserver_netty</artifactId>
+		</dependency>
+	</dependencies>
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-shade-plugin</artifactId>
+				<executions>
+					<execution>
+						<phase>package</phase>
+						<goals>
+							<goal>shade</goal>
+						</goals>
+						<configuration>
+							<transformers>
+								<transformer
+									implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+									<mainClass>net.officefloor.OfficeFloorMain</mainClass>
+								</transformer>
+							</transformers>
+						</configuration>
+					</execution>
+				</executions>
+			</plugin>
+		</plugins>
+	</build>
+</project>

+ 45 - 0
frameworks/Java/officefloor/src/woof_rapidoid/pom.xml

@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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>
+	<parent>
+		<groupId>net.officefloor.benchmarks</groupId>
+		<artifactId>benchmarks</artifactId>
+		<version>1.0.0</version>
+	</parent>
+	<artifactId>woof_rapidoid</artifactId>
+	<dependencies>
+		<dependency>
+			<groupId>net.officefloor.benchmarks</groupId>
+			<artifactId>woof_benchmark</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>net.officefloor.server</groupId>
+			<artifactId>officeserver_rapidoid</artifactId>
+		</dependency>
+	</dependencies>
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-shade-plugin</artifactId>
+				<executions>
+					<execution>
+						<phase>package</phase>
+						<goals>
+							<goal>shade</goal>
+						</goals>
+						<configuration>
+							<transformers>
+								<transformer
+									implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+									<mainClass>net.officefloor.OfficeFloorMain</mainClass>
+								</transformer>
+							</transformers>
+						</configuration>
+					</execution>
+				</executions>
+			</plugin>
+		</plugins>
+	</build>
+</project>

+ 54 - 0
frameworks/Java/officefloor/src/woof_raw/pom.xml

@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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>
+	<parent>
+		<groupId>net.officefloor.benchmarks</groupId>
+		<artifactId>benchmarks</artifactId>
+		<version>1.0.0</version>
+	</parent>
+	<artifactId>woof_raw</artifactId>
+	<dependencies>
+		<dependency>
+			<groupId>net.officefloor.web</groupId>
+			<artifactId>woof</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>com.fasterxml.jackson.core</groupId>
+			<artifactId>jackson-databind</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>com.fasterxml.jackson.module</groupId>
+			<artifactId>jackson-module-afterburner</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.projectlombok</groupId>
+			<artifactId>lombok</artifactId>
+			<scope>provided</scope>
+		</dependency>
+	</dependencies>
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-shade-plugin</artifactId>
+				<executions>
+					<execution>
+						<phase>package</phase>
+						<goals>
+							<goal>shade</goal>
+						</goals>
+						<configuration>
+							<transformers>
+								<transformer
+									implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+									<mainClass>net.officefloor.benchmark.RawOfficeFloorMain</mainClass>
+								</transformer>
+							</transformers>
+						</configuration>
+					</execution>
+				</executions>
+			</plugin>
+		</plugins>
+	</build>
+</project>

+ 213 - 0
frameworks/Java/officefloor/src/woof_raw/src/main/java/net/officefloor/benchmark/RawOfficeFloorMain.java

@@ -0,0 +1,213 @@
+/*
+ * OfficeFloor - http://www.officefloor.net
+ * Copyright (C) 2005-2018 Daniel Sagenschneider
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package net.officefloor.benchmark;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import lombok.Data;
+import net.officefloor.frame.api.manage.OfficeFloor;
+import net.officefloor.frame.api.managedobject.ProcessAwareContext;
+import net.officefloor.frame.api.managedobject.ProcessSafeOperation;
+import net.officefloor.server.SocketManager;
+import net.officefloor.server.http.AbstractHttpServicerFactory;
+import net.officefloor.server.http.HttpHeaderName;
+import net.officefloor.server.http.HttpHeaderValue;
+import net.officefloor.server.http.HttpRequest;
+import net.officefloor.server.http.HttpResponse;
+import net.officefloor.server.http.HttpResponseHeaders;
+import net.officefloor.server.http.HttpServerLocation;
+import net.officefloor.server.http.HttpServerSocketManagedObjectSource;
+import net.officefloor.server.http.HttpStatus;
+import net.officefloor.server.http.ServerHttpConnection;
+import net.officefloor.server.http.impl.HttpServerLocationImpl;
+import net.officefloor.server.http.impl.ProcessAwareServerHttpConnectionManagedObject;
+import net.officefloor.server.http.parse.HttpRequestParser.HttpRequestParserMetaData;
+import net.officefloor.server.stream.StreamBufferPool;
+import net.officefloor.server.stream.impl.ThreadLocalStreamBufferPool;
+
+/**
+ * <p>
+ * {@link SocketManager} raw performance.
+ * <p>
+ * Allows determining the overhead of the {@link OfficeFloor} framework.
+ */
+public class RawOfficeFloorMain {
+
+	/**
+	 * {@link SocketManager}.
+	 */
+	public static SocketManager socketManager = null;
+
+	/**
+	 * Run application.
+	 */
+	public static void main(String[] args) throws Exception {
+
+		// Obtain the port from properties
+		int port = args.length > 0 ? Integer.parseInt(args[0]) : 8080;
+
+		// Ensure previous socket manager shutdown (typically from tests)
+		if (socketManager != null) {
+			socketManager.shutdown();
+		}
+
+		// Create the server location
+		HttpServerLocation serverLocation = new HttpServerLocationImpl("localhost", port, -1);
+
+		// Create the socket manager
+		socketManager = HttpServerSocketManagedObjectSource.createSocketManager();
+
+		// Create raw HTTP servicing
+		StreamBufferPool<ByteBuffer> serviceBufferPool = new ThreadLocalStreamBufferPool(
+				() -> ByteBuffer.allocateDirect(8046), Integer.MAX_VALUE, Integer.MAX_VALUE);
+		RawHttpServicerFactory serviceFactory = new RawHttpServicerFactory(serverLocation, serviceBufferPool);
+		socketManager.bindServerSocket(serverLocation.getClusterHttpPort(), null, null, serviceFactory, serviceFactory);
+
+		// Setup Date
+		Timer dateTimer = new Timer(true);
+		dateTimer.schedule(serviceFactory.updateDate, 0, 1000);
+
+		// Start servicing
+		Executor executor = Executors.newCachedThreadPool();
+		for (Runnable runnable : socketManager.getRunnables()) {
+			executor.execute(runnable);
+		}
+
+		// Indicate running
+		System.out.println("OfficeFloor raw running");
+	}
+
+	/**
+	 * Raw {@link AbstractHttpServicerFactory}.
+	 */
+	private static class RawHttpServicerFactory extends AbstractHttpServicerFactory {
+
+		private static HttpHeaderName NAME_SERVER = new HttpHeaderName("Server");
+
+		private static HttpHeaderValue VALUE_SERVER = new HttpHeaderValue("OF");
+
+		private static HttpHeaderName NAME_DATE = new HttpHeaderName("Date");
+
+		private static byte[] HELLO_WORLD = "Hello, World!".getBytes(ServerHttpConnection.DEFAULT_HTTP_ENTITY_CHARSET);
+
+		private static HttpHeaderValue APPLICATION_JSON = new HttpHeaderValue("application/json");
+
+		private static final HttpHeaderValue TEXT_PLAIN = new HttpHeaderValue("text/plain");
+
+		/**
+		 * <code>Date</code> {@link HttpHeaderValue}.
+		 */
+		private volatile HttpHeaderValue dateHttpHeader;
+
+		private final TimerTask updateDate = new TimerTask() {
+			@Override
+			public void run() {
+				String now = DateTimeFormatter.RFC_1123_DATE_TIME.format(ZonedDateTime.now(ZoneOffset.UTC));
+				RawHttpServicerFactory.this.dateHttpHeader = new HttpHeaderValue(now);
+			}
+		};
+
+		/**
+		 * {@link ObjectMapper}.
+		 */
+		private final ObjectMapper objectMapper = new ObjectMapper();
+
+		/**
+		 * {@link ProcessAwareContext}.
+		 */
+		private static ProcessAwareContext processAwareContext = new ProcessAwareContext() {
+			@Override
+			public <R, T extends Throwable> R run(ProcessSafeOperation<R, T> operation) throws T {
+				return operation.run();
+			}
+		};
+
+		/**
+		 * Instantiate.
+		 *
+		 * @param serverLocation    {@link HttpServerLocation}.
+		 * @param serviceBufferPool {@link StreamBufferPool}.
+		 */
+		public RawHttpServicerFactory(HttpServerLocation serverLocation,
+				StreamBufferPool<ByteBuffer> serviceBufferPool) {
+			super(serverLocation, false, new HttpRequestParserMetaData(100, 1000, 1000000), serviceBufferPool, 1000,
+					null, null, true);
+		}
+
+		/*
+		 * ===================== HttpServicer ====================
+		 */
+
+		@Override
+		protected void service(ProcessAwareServerHttpConnectionManagedObject<ByteBuffer> connection)
+				throws IOException {
+
+			// Configure process awareness
+			connection.setProcessAwareContext(processAwareContext);
+
+			// Service the connection
+			HttpRequest request = connection.getRequest();
+			HttpResponse response = connection.getResponse();
+
+			// Provider Server and Date
+			HttpResponseHeaders headers = response.getHeaders();
+			headers.addHeader(NAME_SERVER, VALUE_SERVER);
+			headers.addHeader(NAME_DATE, this.dateHttpHeader);
+
+			// Determine request
+			String requestUri = request.getUri();
+			switch (requestUri) {
+			case "/plaintext":
+				response.setContentType(TEXT_PLAIN, null);
+				response.getEntity().write(HELLO_WORLD);
+				break;
+
+			case "/json":
+				response.setContentType(APPLICATION_JSON, null);
+				this.objectMapper.writeValue(response.getEntityWriter(), new Message("Hello, World!"));
+				break;
+
+			default:
+				response.setStatus(HttpStatus.NOT_FOUND);
+				break;
+			}
+
+			try {
+				connection.getServiceFlowCallback().run(null);
+			} catch (Throwable ex) {
+				throw new IOException(ex);
+			}
+		}
+	}
+
+	@Data
+	public static class Message {
+		private final String message;
+	}
+
+}

+ 2 - 1
tfb

@@ -101,4 +101,5 @@ if ! docker network inspect tfb >/dev/null 2>&1; then
   docker network create tfb >/dev/null
 fi
 
-exec docker run -it --rm --network tfb -v /var/run/docker.sock:/var/run/docker.sock -v ${SCRIPT_ROOT}:/FrameworkBenchmarks techempower/tfb "${@}"
+test -t 1 && USE_TTY="-t"
+exec docker run -i ${USE_TTY} --rm --network tfb -v /var/run/docker.sock:/var/run/docker.sock -v ${SCRIPT_ROOT}:/FrameworkBenchmarks techempower/tfb "${@}"