Przeglądaj źródła

Java/servlet Caching implementation and updates (#2906)

* Update dependencies. Minor code cleanup

* cache2k cashing implementation

* Update benchmark_config.json

* Update the cached query URL

* More clean up

* Add Maven build profiles for modular webapp assembly

* Maven clean install

* Use correct database hostname

* Add missing dependencies for the shell scripts

* Updated documentation. Removed duplicated servlet code. Minor code clean up
Radoslav Petrov 8 lat temu
rodzic
commit
8ab7a8c7c4
24 zmienionych plików z 593 dodań i 635 usunięć
  1. 3 3
      frameworks/Java/jetty/README.md
  2. 36 12
      frameworks/Java/servlet/README.md
  3. 5 4
      frameworks/Java/servlet/benchmark_config.json
  4. 100 28
      frameworks/Java/servlet/pom.xml
  5. 1 3
      frameworks/Java/servlet/setup.sh
  6. 5 2
      frameworks/Java/servlet/setup_mysql.sh
  7. 5 2
      frameworks/Java/servlet/setup_postgresql.sh
  8. 68 0
      frameworks/Java/servlet/src/main/java/hello/Cache2kPostgresServlet.java
  9. 9 0
      frameworks/Java/servlet/src/main/java/hello/CachedWorld.java
  10. 47 22
      frameworks/Java/servlet/src/main/java/hello/Common.java
  11. 60 94
      frameworks/Java/servlet/src/main/java/hello/DbPoolServlet.java
  12. 57 57
      frameworks/Java/servlet/src/main/java/hello/FortunesServlet.java
  13. 0 75
      frameworks/Java/servlet/src/main/java/hello/PostgreFortunesServlet.java
  14. 0 106
      frameworks/Java/servlet/src/main/java/hello/PostgresServlet.java
  15. 34 53
      frameworks/Java/servlet/src/main/java/hello/PostgresUpdateServlet.java
  16. 25 47
      frameworks/Java/servlet/src/main/java/hello/UpdateServlet.java
  17. 20 25
      frameworks/Java/servlet/src/main/java/hello/World.java
  18. 15 0
      frameworks/Java/servlet/src/main/resources/WEB-INF/mysql/resin-web.xml
  19. 37 0
      frameworks/Java/servlet/src/main/resources/WEB-INF/mysql/web.xml
  20. 12 0
      frameworks/Java/servlet/src/main/resources/WEB-INF/postgresql/resin-web.xml
  21. 46 0
      frameworks/Java/servlet/src/main/resources/WEB-INF/postgresql/web.xml
  22. 8 18
      frameworks/Java/servlet/src/main/webapp/WEB-INF/jsp/fortunes.jsp
  23. 0 22
      frameworks/Java/servlet/src/main/webapp/WEB-INF/resin-web.xml
  24. 0 62
      frameworks/Java/servlet/src/main/webapp/WEB-INF/web.xml

+ 3 - 3
frameworks/Java/jetty/README.md

@@ -4,14 +4,14 @@ This is the Jetty portion of a [benchmarking test suite](../) comparing a variet
 
 ## Handler
 
-### JSON Encoding Test
+These implementations use the Jetty's custom handler interface.
 * [Plaintext test source](src/main/java/hello/handler/PlainTextHandler.java)
 * [JSON test source](src/main/java/hello/handler/JsonHandler.java)
 
 ## Servlet
 
-### JSON Encoding Test
-* [Plaintext test source](src/main/java/hello/handler/PlaintextServlet.java)
+These implementation are using the standart servlet API.
+* [Plaintext test source](src/main/java/hello/servlet/PlaintextServlet.java)
 * [JSON test source](src/main/java/hello/servlet/JsonServlet.java)
 
 ## Versions

+ 36 - 12
frameworks/Java/servlet/README.md

@@ -1,29 +1,53 @@
-#Servlet Benchmarking Test
+# Servlet Benchmarking Test
 
 This is the Java Servlet portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
 
-### JSON Encoding Test
-For raw Servlets there is no broad consensus on JSON encoding so we have selected the fastest available JSON encoder for Java: [Jackson](http://wiki.fasterxml.com/JacksonHome).
+### Plaintext and JSON
 
+* [Plaintext test source](src/main/java/hello/PlaintextServlet.java)
 * [JSON test source](src/main/java/hello/JsonServlet.java)
 
-### Data-Store/Database Mapping Test
+### `MySQL` implementation
+
 * [DB test source](src/main/java/hello/DbPoolServlet.java)
+* [Queries test source](src/main/java/hello/DbPoolServlet.java)
+* [Updates test source](src/main/java/hello/UpdateServlet.java) - using `batch updates`
+* [Fortune test source](src/main/java/hello/FortunesServlet.java)
+
+### `PostgreSQL` implementation
+
+DB, Queries and Fortune use the same implementation as MySQL.
+
+* [Updates test source](src/main/java/hello/PostgresUpdateServlet.java) - **not** using `batch updates` due to transaction deadlocks
+* [Cache test source](src/main/java/hello/Cache2kPostgresServlet.java)
 
 ## Infrastructure Software Versions
+
 The tests were run with:
 
-* [Java OpenJDK 1.7.0_09](http://openjdk.java.net/)
-* [Resin 4.0.34](http://www.caucho.com/)
-* [Jackson 2.3.0](http://wiki.fasterxml.com/JacksonHome)
-* [MySQL 5.5.29](https://dev.mysql.com/)
+* [Java Oracle JDK 1.8.0](http://openjdk.java.net/)
+* [Resin 4.0.53](http://www.caucho.com/)
+* [Jackson 2.8.9](http://wiki.fasterxml.com/JacksonHome)
+* [MySQL 5.7](https://dev.mysql.com/)
+* [Postgres 9.3](http://www.postgresql.org/)
+* [cache2k 1.0.0.CR4](https://cache2k.org/)
+
+Please confirm the versions data with the latest install scripts of TFB project.
 
 ## Test URLs
-### JSON Encoding Test
 
-http://localhost:8080/servlet/json
+### Default maven profile
+
+ * Plaintext - `http://localhost:8080/servlet/plaintext`
+ * JSON - `http://localhost:8080/servlet/json`
 
-### Data-Store/Database Mapping Test
+### `mysql` and `postgresql` Maven profiles
 
-http://localhost:8080/servlet/db?queries=5
+ * DB - `http://localhost:8080/servlet/db`
+ * Queries - `http://localhost:8080/servlet/db?queries=`
+ * Updates - `http://localhost:8080/servlet/update?queries=`
+ * Fortune - `http://localhost:8080/servlet/fortunes`
 
+### `postgresql` Maven profile
+ 
+ * Cache - `http://localhost:8080/servlet/cached-worlds`

+ 5 - 4
frameworks/Java/servlet/benchmark_config.json

@@ -44,10 +44,11 @@
     },
     "postgres-raw": {
       "setup_file": "setup_postgresql",
-      "db_url": "/servlet/postgres",
-      "query_url": "/servlet/postgres?queries=",
-      "fortune_url": "/servlet/postgres-fortunes",
-      "update_url": "/servlet/postgres-update?queries=",
+      "db_url": "/servlet/db",
+      "query_url": "/servlet/db?queries=",
+      "cached_query_url": "/servlet/cached-worlds?queries=",
+      "fortune_url": "/servlet/fortunes",
+      "update_url": "/servlet/update?queries=",
       "port": 8080,
       "approach": "Realistic",
       "classification": "Platform",

+ 100 - 28
frameworks/Java/servlet/pom.xml

@@ -1,40 +1,34 @@
 <?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">
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 	<modelVersion>4.0.0</modelVersion>
 	<groupId>hello.world</groupId>
 	<artifactId>world</artifactId>
 	<name>Servlet</name>
 	<packaging>war</packaging>
 	<version>1.0.0-BUILD-SNAPSHOT</version>
+
 	<properties>
+		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 		<java-version>1.8</java-version>
+		<cache2k-version>1.0.0.CR4</cache2k-version>
+		<!-- This is the default web.xml for plaintext and json only -->
+		<maven.war.xml>src/main/webapp/WEB-INF/web.xml</maven.war.xml>
 	</properties>
-	<dependencies>
-		<dependency>
-			<groupId>mysql</groupId>
-			<artifactId>mysql-connector-java</artifactId>
-			<version>5.1.38</version>
-		</dependency>
-
-		<dependency>
-			<groupId>org.postgresql</groupId>
-			<artifactId>postgresql</artifactId>
-			<version>9.4.1208</version>
-		</dependency>
-
 
+	<dependencies>
 		<dependency>
 			<groupId>com.fasterxml.jackson.core</groupId>
 			<artifactId>jackson-databind</artifactId>
-			<version>2.8.7</version>
+			<version>2.8.9</version>
 		</dependency>
 
 		<dependency>
-			<groupId>jstl</groupId>
-			<artifactId>jstl</artifactId>
-			<version>1.2</version>
+			<groupId>org.apache.taglibs</groupId>
+			<artifactId>taglibs-standard-impl</artifactId>
+			<version>1.2.5</version>
 		</dependency>
+
 		<!-- @Inject -->
 		<dependency>
 			<groupId>javax.inject</groupId>
@@ -50,20 +44,100 @@
 			<scope>provided</scope>
 		</dependency>
 
-		<!-- Apache Commons Lang -->
+		<!-- cache2k -->
 		<dependency>
-			<groupId>org.apache.commons</groupId>
-			<artifactId>commons-lang3</artifactId>
-			<version>3.5</version>
+			<groupId>org.cache2k</groupId>
+			<artifactId>cache2k-api</artifactId>
+			<version>${cache2k-version}</version>
+			<scope>provided</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.cache2k</groupId>
+			<artifactId>cache2k-all</artifactId>
+			<version>${cache2k-version}</version>
+			<scope>runtime</scope>
 		</dependency>
-
 	</dependencies>
 
+	<profiles>
+		<profile>
+			<id>mysql</id>
+			<properties>
+				<maven.war.xml>src/main/resources/WEB-INF/mysql/web.xml</maven.war.xml>
+			</properties>
+			<dependencies>
+				<dependency>
+					<groupId>mysql</groupId>
+					<artifactId>mysql-connector-java</artifactId>
+					<version>5.1.42</version>
+				</dependency>
+			</dependencies>
+			<build>
+				<plugins>
+					<plugin>
+						<groupId>org.apache.maven.plugins</groupId>
+						<artifactId>maven-war-plugin</artifactId>
+						<configuration>
+							<webResources>
+								<resource>
+									<directory>src/main/resources/WEB-INF/mysql</directory>
+									<includes>
+										<include>resin-web.xml</include>
+									</includes>
+									<excludes>
+										<exclude>src/main/resources/WEB-INF/</exclude>
+									</excludes>
+									<targetPath>WEB-INF</targetPath>
+								</resource>
+							</webResources>
+						</configuration>
+					</plugin>
+				</plugins>
+			</build>
+		</profile>
+		<profile>
+			<id>postgresql</id>
+			<properties>
+				<maven.war.xml>src/main/resources/WEB-INF/postgresql/web.xml</maven.war.xml>
+			</properties>
+			<dependencies>
+				<dependency>
+					<groupId>org.postgresql</groupId>
+					<artifactId>postgresql</artifactId>
+					<version>42.1.1</version>
+				</dependency>
+			</dependencies>
+			<build>
+				<plugins>
+					<plugin>
+						<groupId>org.apache.maven.plugins</groupId>
+						<artifactId>maven-war-plugin</artifactId>
+						<configuration>
+							<webResources>
+								<resource>
+									<directory>src/main/resources/WEB-INF/postgresql</directory>
+									<includes>
+										<include>resin-web.xml</include>
+									</includes>
+									<excludes>
+										<exclude>src/main/resources/WEB-INF/</exclude>
+									</excludes>
+									<targetPath>WEB-INF</targetPath>
+								</resource>
+							</webResources>
+						</configuration>
+					</plugin>
+				</plugins>
+			</build>
+		</profile>
+	</profiles>
+
 	<build>
 		<plugins>
 			<plugin>
 				<groupId>org.apache.maven.plugins</groupId>
 				<artifactId>maven-compiler-plugin</artifactId>
+				<version>2.3.2</version>
 				<configuration>
 					<source>${java-version}</source>
 					<target>${java-version}</target>
@@ -74,15 +148,13 @@
 			<plugin>
 				<groupId>org.apache.maven.plugins</groupId>
 				<artifactId>maven-war-plugin</artifactId>
+				<version>3.1.0</version>
 				<configuration>
 					<warName>servlet</warName>
+					<!-- Use the web.xml from the current profile -->
+					<webXml>${maven.war.xml}</webXml>
 				</configuration>
 			</plugin>
-			<plugin>
-				<groupId>org.codehaus.mojo</groupId>
-				<artifactId>tomcat-maven-plugin</artifactId>
-				<version>1.1</version>
-			</plugin>
 		</plugins>
 	</build>
 </project>

+ 1 - 3
frameworks/Java/servlet/setup.sh

@@ -1,10 +1,8 @@
 #!/bin/bash
 
-sed -i 's|localhost|'"${DBHOST}"'|g' src/main/webapp/WEB-INF/resin-web.xml
-
 fw_depends java resin maven
 
-mvn clean compile war:war
+mvn clean install
 rm -rf $RESIN_HOME/webapps/*
 cp target/servlet.war $RESIN_HOME/webapps/
 resinctl start

+ 5 - 2
frameworks/Java/servlet/setup_mysql.sh

@@ -1,5 +1,8 @@
 #!/bin/bash
 
-fw_depends mysql
+fw_depends java resin maven mysql
 
-source ./setup.sh
+mvn clean compile war:war -P mysql
+rm -rf $RESIN_HOME/webapps/*
+cp target/servlet.war $RESIN_HOME/webapps/
+resinctl start

+ 5 - 2
frameworks/Java/servlet/setup_postgresql.sh

@@ -1,5 +1,8 @@
 #!/bin/bash
 
-fw_depends postgresql
+fw_depends java resin maven postgresql
 
-source ./setup.sh
+mvn clean compile war:war -P postgresql
+rm -rf $RESIN_HOME/webapps/*
+cp target/servlet.war $RESIN_HOME/webapps/
+resinctl start

+ 68 - 0
frameworks/Java/servlet/src/main/java/hello/Cache2kPostgresServlet.java

@@ -0,0 +1,68 @@
+package hello;
+
+import java.io.*;
+import java.sql.*;
+import java.util.*;
+import java.util.concurrent.*;
+
+import javax.annotation.*;
+import javax.servlet.*;
+import javax.servlet.http.*;
+import javax.sql.*;
+
+import org.cache2k.Cache;
+import org.cache2k.Cache2kBuilder;
+
+/**
+ * Cache
+ */
+@SuppressWarnings("serial")
+public class Cache2kPostgresServlet extends HttpServlet {
+	// Database details.
+	private static final int DB_ROWS = 10000;
+	private static final int LIMIT = DB_ROWS + 1;
+	
+	// Database connection pool.
+	@Resource(name = "jdbc/hello_world")
+	private DataSource dataSource;
+	private Cache<Integer, CachedWorld> cache;
+
+	@Override
+	public void init(ServletConfig config) throws ServletException {
+		super.init(config);
+
+		Map<Integer, CachedWorld> worlds;
+		try {
+			worlds = Common.loadAll(dataSource.getConnection());
+		} catch (SQLException e) {
+			throw new ServletException(e);
+		}
+		
+		// Build the cache
+		cache = new Cache2kBuilder<Integer, CachedWorld>() {}
+		    .name("cachedWorld")
+		    .eternal(true)
+		    .entryCapacity(DB_ROWS)
+		    .build();
+		cache.putAll(worlds);
+	}
+
+	@Override
+	protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException,
+			IOException {
+		final int count = Common.normalise(req.getParameter("queries"));
+		final Random random = ThreadLocalRandom.current();
+
+		//TODO prevent duplicate numbers to be added
+		List<Integer> keys = new ArrayList<Integer>(count);
+		for (int i = 0; i < count; i++) {
+			keys.add(new Integer(random.nextInt(LIMIT)));
+		}
+		
+		// Set content type to JSON
+		res.setHeader(Common.HEADER_CONTENT_TYPE, Common.CONTENT_TYPE_JSON);
+
+		// Write JSON encoded message to the response.
+		Common.MAPPER.writeValue(res.getOutputStream(), cache.getAll(keys).values());
+	}
+}

+ 9 - 0
frameworks/Java/servlet/src/main/java/hello/CachedWorld.java

@@ -0,0 +1,9 @@
+package hello;
+
+public class CachedWorld extends World {
+
+	public CachedWorld(int id, int randomNumber) {
+		super(id, randomNumber);
+	}
+
+}

+ 47 - 22
frameworks/Java/servlet/src/main/java/hello/Common.java

@@ -1,31 +1,56 @@
 package hello;
 
-import org.apache.commons.lang3.*;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Map;
 
 import com.fasterxml.jackson.databind.*;
 
 /**
  * Some common functionality and constants used by the Servlet tests.
  */
-public class Common
-{
+public class Common {
+	// Constants for setting the content type.
+	protected static final String HEADER_CONTENT_TYPE = "Content-Type";
+	protected static final String CONTENT_TYPE_JSON = "application/json";
+	protected static final String CONTENT_TYPE_TEXT = "text/plain";
+	protected static final String CONTENT_TYPE_HTML = "text/html";
 
-  // Constants for setting the content type.
-  protected static final String HEADER_CONTENT_TYPE    = "Content-Type";
-  protected static final String CONTENT_TYPE_JSON      = "application/json";
-  protected static final String CONTENT_TYPE_TEXT      = "text/plain";
-  protected static final String CONTENT_TYPE_HTML      = "text/html";
-
-  // Jackson encoder, reused for each response.
-  protected static final ObjectMapper MAPPER = new ObjectMapper();
-
-  /**
-   * Use the OWASP ESAPI HTML encoder to process an untrusted String into a
-   * form suitable for rendering in output HTML.
-   */
-  public static String render(String input)
-  {
-    return StringEscapeUtils.escapeHtml4(input);        
-  }
-  
-}
+	// Jackson encoder, reused for each response.
+	protected static final ObjectMapper MAPPER = new ObjectMapper();
+	
+	private static final String DB_QUERY = "SELECT * FROM world";
+	
+	public static int normalise(String param) {
+		int count = 1;
+		try {
+			count = Integer.parseInt(param);
+			// Bounds checks
+			if (count > 500) {
+				return 500;
+			} else if (count < 1) {
+				return 1;
+			}
+		} catch (NumberFormatException nfexc) {
+		}
+		return count;
+	}
+	
+	public static Map<Integer, CachedWorld> loadAll(Connection connection) throws SQLException{
+		// Fetch all rows from the database.
+		final Map<Integer, CachedWorld> worlds = new HashMap<Integer, CachedWorld>();
+		try (Connection conn = connection;
+				PreparedStatement statement = conn.prepareStatement(DB_QUERY,
+						ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
+				ResultSet results = statement.executeQuery()) {
+			while (results.next()) {
+				CachedWorld some =  new CachedWorld(results.getInt("id"), results.getInt("randomNumber"));
+				worlds.put(new Integer(some.getId()), some);
+			}
+		}
+		return worlds;
+	}
+}

+ 60 - 94
frameworks/Java/servlet/src/main/java/hello/DbPoolServlet.java

@@ -1,105 +1,71 @@
 package hello;
 
-import java.io.*;
-import java.sql.*;
-import java.util.*;
-import java.util.concurrent.*;
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Random;
+import java.util.concurrent.ThreadLocalRandom;
 
-import javax.annotation.*;
-import javax.servlet.*;
-import javax.servlet.http.*;
-import javax.sql.*;
+import javax.annotation.Resource;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.sql.DataSource;
 
 /**
  * Database connectivity (with a Servlet-container managed pool) test.
  */
 @SuppressWarnings("serial")
-public class DbPoolServlet extends HttpServlet
-{
-  // Database details.
-  private static final String DB_QUERY = "SELECT * FROM World WHERE id = ?";
-  private static final int    DB_ROWS  = 10000;
+public class DbPoolServlet extends HttpServlet {
+	// Database details.
+	private static final String DB_QUERY = "SELECT * FROM World WHERE id = ?";
+	private static final int DB_ROWS = 10000;
+	private static final int LIMIT = DB_ROWS + 1;
 
-  // Database connection pool.
-  @Resource(name="jdbc/hello_world")
-  private DataSource mysqlDataSource;
-    
-  @Override
-  protected void doGet(HttpServletRequest req, HttpServletResponse res)
-      throws ServletException, IOException
-  {
-    // Set content type to JSON
-    res.setHeader(Common.HEADER_CONTENT_TYPE, Common.CONTENT_TYPE_JSON);
+	// Database connection pool.
+	@Resource(name = "jdbc/hello_world")
+	private DataSource dataSource;
 
-    // Reference the data source.
-    final DataSource source = mysqlDataSource;
-    
-    // Get the count of queries to run.
-    int count = 1;
-    try
-    {
-      count = Integer.parseInt(req.getParameter("queries"));
-      
-      // Bounds check.
-      if (count > 500)
-      {
-        count = 500;
-      }
-      if (count < 1)
-      {
-        count = 1;
-      }
-    }
-    catch (NumberFormatException nfexc)
-    {
-      // Do nothing.
-    }
+	@Override
+	protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException,
+			IOException {
+		// Reference the data source.
+		final DataSource source = dataSource;
+		final int count = Common.normalise(req.getParameter("queries"));
+		final World[] worlds = new World[count];
+		final Random random = ThreadLocalRandom.current();
 
-    // Fetch some rows from the database.
-    final World[] worlds = new World[count];
-    final Random random = ThreadLocalRandom.current();
-    
-    try (Connection conn = source.getConnection())
-    {
-      try (PreparedStatement statement = conn.prepareStatement(DB_QUERY, 
-          ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY))
-      {
-        // Run the query the number of times requested.
-        for (int i = 0; i < count; i++)
-        {
-          final int id = random.nextInt(DB_ROWS) + 1;
-          statement.setInt(1, id);
-          
-          try (ResultSet results = statement.executeQuery())
-          {
-            if (results.next())
-            {
-              worlds[i] = new World(id, results.getInt("randomNumber"));
-            }
-          }
-        }
-      }
-    }
-    catch (SQLException sqlex)
-    {
-      System.err.println("SQL Exception: " + sqlex);
-    }
-    
-    // Write JSON encoded message to the response.
-    try
-    {
-      if (count == 1)
-      {
-        Common.MAPPER.writeValue(res.getOutputStream(), worlds[0]); 
-      }
-      else
-      {
-        Common.MAPPER.writeValue(res.getOutputStream(), worlds);
-      }
-    }
-    catch (IOException ioe) 
-    {
-      // do nothing
-    }
-  }
-}
+		// Fetch some rows from the database.
+		try (Connection conn = source.getConnection()) {
+			try (PreparedStatement statement = conn.prepareStatement(DB_QUERY,
+					ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)) {
+				// Run the query the number of times requested.
+				for (int i = 0; i < count; i++) {
+					final int id = random.nextInt(LIMIT);
+					statement.setInt(1, id);
+
+					try (ResultSet results = statement.executeQuery()) {
+						if (results.next()) {
+							worlds[i] = new World(id, results.getInt("randomNumber"));
+						}
+					}
+				}
+			}
+		} catch (SQLException sqlex) {
+			throw new ServletException(sqlex);
+		}
+
+		// Set content type to JSON
+		res.setHeader(Common.HEADER_CONTENT_TYPE, Common.CONTENT_TYPE_JSON);
+
+		// Write JSON encoded message to the response.
+		if (count == 1) {
+			Common.MAPPER.writeValue(res.getOutputStream(), worlds[0]);
+		} else {
+			Common.MAPPER.writeValue(res.getOutputStream(), worlds);
+		}
+	}
+}

+ 57 - 57
frameworks/Java/servlet/src/main/java/hello/FortunesServlet.java

@@ -1,67 +1,67 @@
 package hello;
 
-import java.io.*;
-import java.sql.*;
-import java.util.*;
+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.Collections;
+import java.util.List;
 
-import javax.annotation.*;
-import javax.servlet.*;
-import javax.servlet.http.*;
-import javax.sql.*;
+import javax.annotation.Resource;
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.sql.DataSource;
 
 /**
- * Fortunes test, returns a list of fortune cookie messages fetched from
- * a database table and then composed by server-side templates.
+ * Fortunes test, returns a list of fortune cookie messages fetched from a
+ * database table and then composed by server-side templates.
  */
 @SuppressWarnings("serial")
-public class FortunesServlet extends HttpServlet
-{
-  
-  // Database details.
-  private static final String DB_QUERY = "SELECT * FROM Fortune";
-  private static final String UTF8 = "UTF-8";
-  private static final String CONTENT_TYPE_HTML_UTF8 = "text/html;charset=UTF-8";
+public class FortunesServlet extends HttpServlet {
 
-  // Database connection pool.
-  @Resource(name="jdbc/hello_world")
-  private DataSource mysqlDataSource;
-  
-  @Override
-  protected void doGet(HttpServletRequest req, HttpServletResponse res)
-      throws ServletException, IOException
-  {
-    // Set content type to JSON
-    res.setCharacterEncoding(UTF8);
-    res.setContentType(CONTENT_TYPE_HTML_UTF8);
+	// Database details.
+	private static final String DB_QUERY = "SELECT * FROM Fortune";
+	private static final String UTF8 = "UTF-8";
+	private static final String CONTENT_TYPE_HTML_UTF8 = "text/html;charset=UTF-8";
 
-    final List<Fortune> fortunes = new ArrayList<>();
-    
-    try (
-         Connection conn = mysqlDataSource.getConnection();
-         PreparedStatement statement = conn.prepareStatement(DB_QUERY, 
-             ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
-         ResultSet results = statement.executeQuery()
-        )
-    {
-      while (results.next())
-      {
-        fortunes.add(new Fortune(results.getInt("id"), results.getString("message")));
-      }
-    }
-    catch (SQLException sqlex)
-    {
-      System.err.println("SQL Exception: " + sqlex);
-    }
-    
-    fortunes.add(new Fortune(0, "Additional fortune added at request time."));
-    Collections.sort(fortunes);
-    
-    // Set the list of Fortunes as an attribute of the request, making it
-    // available to the JSP.
-    req.setAttribute("fortunes", fortunes);
-    
-    // Dispatch to the JSP.
-    RequestDispatcher disp = req.getRequestDispatcher("/WEB-INF/jsp/fortunes.jsp");
-    disp.forward(req, res);
-  }
+	// Database connection pool.
+	@Resource(name = "jdbc/hello_world")
+	private DataSource dataSource;
+
+	@Override
+	protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException,
+			IOException {
+		// Set content type to JSON
+		res.setCharacterEncoding(UTF8);
+		res.setContentType(CONTENT_TYPE_HTML_UTF8);
+
+		final List<Fortune> fortunes = new ArrayList<>(32);
+
+		try (Connection conn = dataSource.getConnection();
+				PreparedStatement statement = conn.prepareStatement(DB_QUERY,
+						ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
+				ResultSet results = statement.executeQuery()) {
+			while (results.next()) {
+				fortunes.add(new Fortune(results.getInt("id"), results.getString("message")));
+			}
+		} catch (SQLException sqlex) {
+			throw new ServletException(sqlex);
+		}
+
+		fortunes.add(new Fortune(0, "Additional fortune added at request time."));
+		Collections.sort(fortunes);
+
+		// Set the list of Fortunes as an attribute of the request, making it
+		// available to the JSP.
+		req.setAttribute("fortunes", fortunes);
+
+		// Dispatch to the JSP.
+		RequestDispatcher disp = req.getRequestDispatcher("/WEB-INF/jsp/fortunes.jsp");
+		disp.forward(req, res);
+	}
 }

+ 0 - 75
frameworks/Java/servlet/src/main/java/hello/PostgreFortunesServlet.java

@@ -1,75 +0,0 @@
-package hello;
-
-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.Collections;
-import java.util.List;
-
-import javax.annotation.Resource;
-import javax.servlet.RequestDispatcher;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.sql.DataSource;
-
-/**
- * Fortunes test, returns a list of fortune cookie messages fetched from
- * a database table and then composed by server-side templates.
- */
-@SuppressWarnings("serial")
-public class PostgreFortunesServlet extends HttpServlet
-{
-  
-  // Database details.
-  private static final String DB_QUERY = "SELECT * FROM Fortune";
-  private static final String UTF8 = "UTF-8";
-  private static final String CONTENT_TYPE_HTML_UTF8 = "text/html;charset=UTF-8";
-
-  // Database connection pool.
-  @Resource(name="jdbc/postgres_hello_world")
-  private DataSource postgresDataSource;
-  
-  @Override
-  protected void doGet(HttpServletRequest req, HttpServletResponse res)
-			throws ServletException, IOException
-  {
-    // Set content type to JSON
-    res.setCharacterEncoding(UTF8);
-    res.setContentType(CONTENT_TYPE_HTML_UTF8);
-
-    final List<Fortune> fortunes = new ArrayList<>();
-    
-    try (
-         Connection conn = postgresDataSource.getConnection();
-         PreparedStatement statement = conn.prepareStatement(DB_QUERY, 
-             ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
-         ResultSet results = statement.executeQuery()
-        )
-    {
-      while (results.next())
-      {
-        fortunes.add(new Fortune(results.getInt("id"), results.getString("message")));
-      }
-    }
-    catch (SQLException sqlex)
-    {
-      System.err.println("SQL Exception: " + sqlex);
-    }
-    
-    fortunes.add(new Fortune(0, "Additional fortune added at request time."));
-    Collections.sort(fortunes);
-    
-    // Set the list of Fortunes as an attribute of the request, making it
-    // available to the JSP.
-    req.setAttribute("fortunes", fortunes);
-    
-    // Dispatch to the JSP.
-    RequestDispatcher disp = req.getRequestDispatcher("/WEB-INF/jsp/fortunes.jsp");
-    disp.forward(req, res);
-  }
-}

+ 0 - 106
frameworks/Java/servlet/src/main/java/hello/PostgresServlet.java

@@ -1,106 +0,0 @@
-package hello;
-
-import java.io.*;
-import java.sql.*;
-import java.util.*;
-import java.util.concurrent.*;
-
-import javax.annotation.*;
-import javax.servlet.*;
-import javax.servlet.http.*;
-import javax.sql.*;
-
-/**
- * Database connectivity (with a Servlet-container managed pool) test.
- */
-@SuppressWarnings("serial")
-public class PostgresServlet extends HttpServlet
-{
-  // Database details.
-  private static final String DB_QUERY = "SELECT * FROM World WHERE id = ?";
-  private static final int    DB_ROWS  = 10000;
-
-  // Database connection pool.
-  @Resource(name="jdbc/postgres_hello_world")
-  private DataSource postgresDataSource;
-    
-  @Override
-  protected void doGet(HttpServletRequest req, HttpServletResponse res)
-      throws ServletException, IOException
-  {
-    // Set content type to JSON
-    res.setHeader(Common.HEADER_CONTENT_TYPE, Common.CONTENT_TYPE_JSON);
-
-    // Reference the data source.
-    final DataSource source = postgresDataSource;
-    
-    // Get the count of queries to run.
-    int count = 1;
-    try
-    {
-      count = Integer.parseInt(req.getParameter("queries"));
-      
-      // Bounds check.
-      if (count > 500)
-      {
-        count = 500;
-      }
-      if (count < 1)
-      {
-        count = 1;
-      }
-    }
-    catch (NumberFormatException nfexc)
-    {
-      // Do nothing.
-    }
-
-    // Fetch some rows from the database.
-    final World[] worlds = new World[count];
-    final Random random = ThreadLocalRandom.current();
-    
-    try (Connection conn = source.getConnection())
-    {
-      try (PreparedStatement statement = conn.prepareStatement(DB_QUERY, 
-          ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY))
-      {
-        // Run the query the number of times requested.
-        for (int i = 0; i < count; i++)
-        {
-          final int id = random.nextInt(DB_ROWS) + 1;
-          statement.setInt(1, id);
-          
-          try (ResultSet results = statement.executeQuery())
-          {
-            if (results.next())
-            {
-              worlds[i] = new World(id, results.getInt("randomNumber"));
-            }
-          }
-        }
-      }
-    }
-    catch (SQLException sqlex)
-    {
-      System.err.println("SQL Exception: " + sqlex);
-    }
-    
-    // Write JSON encoded message to the response.
-    try
-    {
-      if (count == 1)
-      {
-        Common.MAPPER.writeValue(res.getOutputStream(), worlds[0]);
-      }
-      else
-      {
-        Common.MAPPER.writeValue(res.getOutputStream(), worlds);
-      }
-    }
-    catch (IOException ioe) 
-    {
-      // do nothing
-    }
-  }
-}
-

+ 34 - 53
frameworks/Java/servlet/src/main/java/hello/PostgresUpdateServlet.java

@@ -20,83 +20,64 @@ import javax.sql.DataSource;
  */
 @SuppressWarnings("serial")
 public class PostgresUpdateServlet extends HttpServlet {
+	private static final String PARAMETER_QUERIES = "queries";
 	// Database details.
 	private static final String DB_QUERY = "SELECT * FROM World WHERE id = ?";
 	private static final String UPDATE_QUERY = "UPDATE World SET randomNumber = ? WHERE id = ?";
 	private static final int DB_ROWS = 10000;
+	private static final int LIMIT = DB_ROWS + 1;
 
 	// Database connection pool.
-	@Resource(name = "jdbc/postgres_hello_world")
-	private DataSource postgresDataSource;
+	@Resource(name = "jdbc/hello_world")
+	private DataSource dataSource;
 
 	@Override
 	protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException,
 			IOException {
-		// Set content type to JSON
-		res.setHeader(Common.HEADER_CONTENT_TYPE, Common.CONTENT_TYPE_JSON);
-
 		// Reference the data source.
-		final DataSource source = postgresDataSource;
-
-		// Get the count of queries to run.
-		int count = 1;
-		try {
-			count = Integer.parseInt(req.getParameter("queries"));
-
-			// Bounds check.
-			if (count > 500) {
-				count = 500;
-			}
-			if (count < 1) {
-				count = 1;
-			}
-		} catch (NumberFormatException nfexc) {
-			// Do nothing.
-		}
-
-		// Fetch some rows from the database.
+		final DataSource source = dataSource;
+		final int count = Common.normalise(req.getParameter(PARAMETER_QUERIES));
 		final World[] worlds = new World[count];
 		final Random random = ThreadLocalRandom.current();
 
-		try (Connection conn = source.getConnection()) {
-			try (PreparedStatement statement = conn.prepareStatement(DB_QUERY,
-					ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
-					PreparedStatement statement2 = conn.prepareStatement(UPDATE_QUERY)) {
-				// Run the query the number of times requested.
-				for (int i = 0; i < count; i++) {
-					final int id = random.nextInt(DB_ROWS) + 1;
-					statement.setInt(1, id);
+		try (Connection conn = source.getConnection();
+				PreparedStatement statement = conn.prepareStatement(DB_QUERY,
+						ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
+				PreparedStatement statement2 = conn.prepareStatement(UPDATE_QUERY)) {
+			// Run the query the number of times requested.
+			for (int i = 0; i < count; i++) {
+				final int id = random.nextInt(LIMIT);
+				statement.setInt(1, id);
 
-					try (ResultSet results = statement.executeQuery()) {
-						if (results.next()) {
-							worlds[i] = new World(id, results.getInt("randomNumber"));
+				try (ResultSet results = statement.executeQuery()) {
+					if (results.next()) {
+						worlds[i] = new World(id, results.getInt("randomNumber"));
 
-							// Update row
-							worlds[i].setRandomNumber(random.nextInt(DB_ROWS) + 1);
-							statement2.setInt(1, worlds[i].getRandomNumber());
-							statement2.setInt(2, id);
+						// Update row
+						worlds[i].setRandomNumber(random.nextInt(LIMIT));
+						statement2.setInt(1, worlds[i].getRandomNumber());
+						statement2.setInt(2, id);
 
-							// Execute the update statement
-							statement2.execute();
+						// Execute the update statement
+						statement2.execute();
 
-							/* 
-							*  Applying batch updates will lead to transaction deadlocks.
-							*  This could not be apparent on local testing but will be
-							*  visible on higher concurrencies in the TFB test  environment.
-							*/
-						}
+						/*
+						 * Applying batch updates will lead to transaction
+						 * deadlocks. This could not be apparent on local
+						 * testing but will be visible on higher concurrencies
+						 * in the TFB test environment.
+						 */
 					}
 				}
 			}
 		} catch (SQLException sqlex) {
-			System.err.println("SQL Exception: " + sqlex);
+			throw new ServletException(sqlex);
 		}
 
+		// Set content type to JSON
+		res.setHeader(Common.HEADER_CONTENT_TYPE, Common.CONTENT_TYPE_JSON);
+
 		// Write JSON encoded message to the response.
-		try {
-			Common.MAPPER.writeValue(res.getOutputStream(), worlds);
-		} catch (IOException ioe) {
-			// do nothing
-		}
+		Common.MAPPER.writeValue(res.getOutputStream(), worlds);
 	}
 }

+ 25 - 47
frameworks/Java/servlet/src/main/java/hello/UpdateServlet.java

@@ -20,10 +20,12 @@ import javax.sql.DataSource;
  */
 @SuppressWarnings("serial")
 public class UpdateServlet extends HttpServlet {
+	private static final String PARAMETER_QUERIES = "queries";
 	// Database details.
 	private static final String DB_QUERY = "SELECT * FROM World WHERE id = ?";
 	private static final String UPDATE_QUERY = "UPDATE World SET randomNumber = ? WHERE id = ?";
 	private static final int DB_ROWS = 10000;
+	private static final int LIMIT = DB_ROWS + 1;
 
 	// Database connection pool.
 	@Resource(name = "jdbc/hello_world")
@@ -32,68 +34,44 @@ public class UpdateServlet extends HttpServlet {
 	@Override
 	protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException,
 			IOException {
-		// Set content type to JSON
-		res.setHeader(Common.HEADER_CONTENT_TYPE, Common.CONTENT_TYPE_JSON);
-
 		// Reference the data source.
 		final DataSource source = mysqlDataSource;
-
-		// Get the count of queries to run.
-		int count = 1;
-		try {
-			count = Integer.parseInt(req.getParameter("queries"));
-
-			// Bounds check.
-			if (count > 500) {
-				count = 500;
-			}
-			if (count < 1) {
-				count = 1;
-			}
-		} catch (NumberFormatException nfexc) {
-			// Do nothing.
-		}
-
-		// Fetch some rows from the database.
+		final int count = Common.normalise(req.getParameter(PARAMETER_QUERIES));
 		final World[] worlds = new World[count];
 		final Random random = ThreadLocalRandom.current();
 
-		try (Connection conn = source.getConnection()) {
-			try (PreparedStatement statement = conn.prepareStatement(DB_QUERY,
-					ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
-					PreparedStatement statement2 = conn.prepareStatement(UPDATE_QUERY,
-							ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)) {
-				// Run the query the number of times requested.
-				for (int i = 0; i < count; i++) {
-					final int id = random.nextInt(DB_ROWS) + 1;
-					statement.setInt(1, id);
+		try (Connection conn = source.getConnection();
+				PreparedStatement statement = conn.prepareStatement(DB_QUERY,
+						ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
+				PreparedStatement statement2 = conn.prepareStatement(UPDATE_QUERY,
+						ResultSet.TYPE_FORWARD_ONLY)) {
+			// Run the query the number of times requested.
+			for (int i = 0; i < count; i++) {
+				final int id = random.nextInt(LIMIT);
+				statement.setInt(1, id);
 
-					try (ResultSet results = statement.executeQuery()) {
-						if (results.next()) {
-							worlds[i] = new World(id, results.getInt("randomNumber"));
+				try (ResultSet results = statement.executeQuery()) {
+					if (results.next()) {
+						worlds[i] = new World(id, results.getInt("randomNumber"));
 
-							// Update row
-							worlds[i].setRandomNumber(random.nextInt(DB_ROWS) + 1);
-							statement2.setInt(1, worlds[i].getRandomNumber());
-							statement2.setInt(2, id);
+						// Update row
+						worlds[i].setRandomNumber(random.nextInt(LIMIT));
+						statement2.setInt(1, worlds[i].getRandomNumber());
+						statement2.setInt(2, id);
 
-							// Add update statement to batch update
-							statement2.addBatch();
-						}
+						// Add update statement to batch update
+						statement2.addBatch();
 					}
 				}
 				// Execute batch update
 				statement2.executeBatch();
 			}
 		} catch (SQLException sqlex) {
-			System.err.println("SQL Exception: " + sqlex);
+			throw new ServletException(sqlex);
 		}
-
+		// Set content type to JSON
+		res.setHeader(Common.HEADER_CONTENT_TYPE, Common.CONTENT_TYPE_JSON);
 		// Write JSON encoded message to the response.
-		try {
-			Common.MAPPER.writeValue(res.getOutputStream(), worlds);
-		} catch (IOException ioe) {
-			// do nothing
-		}
+		Common.MAPPER.writeValue(res.getOutputStream(), worlds);
 	}
 }

+ 20 - 25
frameworks/Java/servlet/src/main/java/hello/World.java

@@ -3,30 +3,25 @@ package hello;
 /**
  * Simple World entity.
  */
-public class World
-{
+public class World {
 
-  private final int id;
-  private int randomNumber;
-  
-  public World(int id, int randomNumber)
-  {
-    this.id = id;
-    this.randomNumber = randomNumber;
-  }
-  
-  public int getId()
-  {
-    return this.id;
-  }
-  
-  public int getRandomNumber()
-  {
-    return this.randomNumber;
-  }      
- 
-  public void setRandomNumber(int randomNumber)
-  {
-    this.randomNumber = randomNumber;
-  } 
+	private final int id;
+	private int randomNumber;
+
+	public World(int id, int randomNumber) {
+		this.id = id;
+		this.randomNumber = randomNumber;
+	}
+
+	public int getId() {
+		return id;
+	}
+
+	public int getRandomNumber() {
+		return randomNumber;
+	}
+
+	public void setRandomNumber(int randomNumber) {
+		this.randomNumber = randomNumber;
+	}
 }

+ 15 - 0
frameworks/Java/servlet/src/main/resources/WEB-INF/mysql/resin-web.xml

@@ -0,0 +1,15 @@
+<web-app xmlns="http://caucho.com/ns/resin">
+
+	<database jndi-name='jdbc/hello_world'>
+		<driver>
+			<type>com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource
+			</type>
+			<url>jdbc:mysql://TFB-database:3306/hello_world?jdbcCompliantTruncation=false&amp;elideSetAutoCommits=true&amp;useLocalSessionState=true&amp;cachePrepStmts=true&amp;cacheCallableStmts=true&amp;alwaysSendSetIsolation=false&amp;prepStmtCacheSize=4096&amp;cacheServerConfiguration=true&amp;prepStmtCacheSqlLimit=2048&amp;zeroDateTimeBehavior=convertToNull&amp;traceProtocol=false&amp;useUnbufferedInput=false&amp;useReadAheadInput=false&amp;maintainTimeStats=false&amp;useServerPrepStmts&amp;cacheRSMetadata=true&amp;useSSL=false
+			</url>
+			<user>benchmarkdbuser</user>
+			<password>benchmarkdbpass</password>
+			<useUnicode />
+		</driver>
+	</database>
+
+</web-app>

+ 37 - 0
frameworks/Java/servlet/src/main/resources/WEB-INF/mysql/web.xml

@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
+	version="2.4">
+	<servlet>
+		<servlet-name>db</servlet-name>
+		<servlet-class>hello.DbPoolServlet</servlet-class>
+		<load-on-startup>1</load-on-startup>
+	</servlet>
+	<servlet-mapping>
+		<servlet-name>db</servlet-name>
+		<url-pattern>/db</url-pattern>
+	</servlet-mapping>
+	<servlet>
+		<servlet-name>fortunes</servlet-name>
+		<servlet-class>hello.FortunesServlet</servlet-class>
+		<load-on-startup>1</load-on-startup>
+	</servlet>
+	<servlet-mapping>
+		<servlet-name>fortunes</servlet-name>
+		<url-pattern>/fortunes</url-pattern>
+	</servlet-mapping>
+	<servlet>
+		<servlet-name>update</servlet-name>
+		<servlet-class>hello.UpdateServlet</servlet-class>
+		<load-on-startup>1</load-on-startup>
+	</servlet>
+	<servlet-mapping>
+		<servlet-name>update</servlet-name>
+		<url-pattern>/update</url-pattern>
+	</servlet-mapping>
+	<resource-env-ref>
+		<resource-env-ref-name>jdbc/hello_world</resource-env-ref-name>
+		<resource-env-ref-type>javax.sql.DataSource</resource-env-ref-type>
+	</resource-env-ref>
+</web-app>

+ 12 - 0
frameworks/Java/servlet/src/main/resources/WEB-INF/postgresql/resin-web.xml

@@ -0,0 +1,12 @@
+<web-app xmlns="http://caucho.com/ns/resin">
+
+	<database jndi-name='jdbc/hello_world'>
+		<driver>
+			<type>org.postgresql.Driver</type><!-- TODO change this with the PooledConnection DS -->
+			<url>jdbc:postgresql://TFB-database:5432/hello_world</url>
+			<user>benchmarkdbuser</user>
+			<password>benchmarkdbpass</password>
+		</driver>
+	</database>
+
+</web-app>

+ 46 - 0
frameworks/Java/servlet/src/main/resources/WEB-INF/postgresql/web.xml

@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
+	version="2.4">
+	<servlet>
+		<servlet-name>postgres</servlet-name>
+		<servlet-class>hello.DbPoolServlet</servlet-class>
+		<load-on-startup>1</load-on-startup>
+	</servlet>
+	<servlet-mapping>
+		<servlet-name>postgres</servlet-name>
+		<url-pattern>/db</url-pattern>
+	</servlet-mapping>
+	<servlet>
+		<servlet-name>postgres-update</servlet-name>
+		<servlet-class>hello.PostgresUpdateServlet</servlet-class>
+		<load-on-startup>1</load-on-startup>
+	</servlet>
+	<servlet-mapping>
+		<servlet-name>postgres-update</servlet-name>
+		<url-pattern>/update</url-pattern>
+	</servlet-mapping>
+	<servlet>
+		<servlet-name>postgres-fortunes</servlet-name>
+		<servlet-class>hello.FortunesServlet</servlet-class>
+		<load-on-startup>1</load-on-startup>
+	</servlet>
+	<servlet-mapping>
+		<servlet-name>postgres-fortunes</servlet-name>
+		<url-pattern>/fortunes</url-pattern>
+	</servlet-mapping>
+	<servlet>
+		<servlet-name>postgresql-cache2k</servlet-name>
+		<servlet-class>hello.Cache2kPostgresServlet</servlet-class>
+		<load-on-startup>1</load-on-startup>
+	</servlet>
+	<servlet-mapping>
+		<servlet-name>postgresql-cache2k</servlet-name>
+		<url-pattern>/cached-worlds</url-pattern>
+	</servlet-mapping>
+	<resource-env-ref>
+		<resource-env-ref-name>jdbc/hello_world</resource-env-ref-name>
+		<resource-env-ref-type>javax.sql.DataSource</resource-env-ref-type>
+	</resource-env-ref>
+</web-app>

+ 8 - 18
frameworks/Java/servlet/src/main/webapp/WEB-INF/jsp/fortunes.jsp

@@ -1,10 +1,5 @@
-<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
-<%@ page import="hello.*,
-                 java.util.*" %><%@ page session="false" %><%
-
-List<Fortune> fortunes = (List)request.getAttribute("fortunes");
-
-%>
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
+<%@ page session="false"%>
 <!DOCTYPE html>
 <html>
 <head>
@@ -12,15 +7,10 @@ List<Fortune> fortunes = (List)request.getAttribute("fortunes");
 </head>
 <body>
 <table>
-<tr>
-<th>id</th>
-<th>message</th>
-</tr>
-<c:forEach var="o" items="${fortunes}">
-<tr>
-<td><c:out value="${o.getId()}" /></td>
-<td><c:out value="${o.getMessage()}" /></td>
-</tr>
+<tr><th>id</th><th>message</th></tr>
+<c:forEach var="fortune" items="${fortunes}">
+<tr><td>${fortune.getId()}</td><td><c:out value="${fortune.getMessage()}" /></td></tr>
 </c:forEach>
-</table></body>
-</html>
+</table>
+</body>
+</html>

+ 0 - 22
frameworks/Java/servlet/src/main/webapp/WEB-INF/resin-web.xml

@@ -1,22 +0,0 @@
-<web-app xmlns="http://caucho.com/ns/resin">
-
-<database jndi-name='jdbc/hello_world'>
-  <driver>
-    <type>com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource</type>
-    <url>jdbc:mysql://localhost:3306/hello_world?jdbcCompliantTruncation=false&amp;elideSetAutoCommits=true&amp;useLocalSessionState=true&amp;cachePrepStmts=true&amp;cacheCallableStmts=true&amp;alwaysSendSetIsolation=false&amp;prepStmtCacheSize=4096&amp;cacheServerConfiguration=true&amp;prepStmtCacheSqlLimit=2048&amp;zeroDateTimeBehavior=convertToNull&amp;traceProtocol=false&amp;useUnbufferedInput=false&amp;useReadAheadInput=false&amp;maintainTimeStats=false&amp;useServerPrepStmts&amp;cacheRSMetadata=true&amp;useSSL=false</url>
-    <user>benchmarkdbuser</user>
-    <password>benchmarkdbpass</password>
-    <useUnicode/>
-  </driver>
-</database>
-
-<database jndi-name='jdbc/postgres_hello_world'>
-  <driver>
-    <type>org.postgresql.Driver</type>
-    <url>jdbc:postgresql://localhost:5432/hello_world</url>
-    <user>benchmarkdbuser</user>
-    <password>benchmarkdbpass</password>
-  </driver>
-</database>
-
-</web-app>

+ 0 - 62
frameworks/Java/servlet/src/main/webapp/WEB-INF/web.xml

@@ -21,66 +21,4 @@
 		<servlet-name>plaintext</servlet-name>
 		<url-pattern>/plaintext</url-pattern>
 	</servlet-mapping>
-	<servlet>
-		<servlet-name>db</servlet-name>
-		<servlet-class>hello.DbPoolServlet</servlet-class>
-		<load-on-startup>1</load-on-startup>
-	</servlet>
-	<servlet-mapping>
-		<servlet-name>db</servlet-name>
-		<url-pattern>/db</url-pattern>
-	</servlet-mapping>
-	<servlet>
-		<servlet-name>fortunes</servlet-name>
-		<servlet-class>hello.FortunesServlet</servlet-class>
-		<load-on-startup>1</load-on-startup>
-	</servlet>
-	<servlet-mapping>
-		<servlet-name>fortunes</servlet-name>
-		<url-pattern>/fortunes</url-pattern>
-	</servlet-mapping>
-	<servlet>
-		<servlet-name>update</servlet-name>
-		<servlet-class>hello.UpdateServlet</servlet-class>
-		<load-on-startup>1</load-on-startup>
-	</servlet>
-	<servlet-mapping>
-		<servlet-name>update</servlet-name>
-		<url-pattern>/update</url-pattern>
-	</servlet-mapping>
-	<servlet>
-		<servlet-name>postgres</servlet-name>
-		<servlet-class>hello.PostgresServlet</servlet-class>
-		<load-on-startup>1</load-on-startup>
-	</servlet>
-	<servlet-mapping>
-		<servlet-name>postgres</servlet-name>
-		<url-pattern>/postgres</url-pattern>
-	</servlet-mapping>
-	<servlet>
-		<servlet-name>postgres-update</servlet-name>
-		<servlet-class>hello.PostgresUpdateServlet</servlet-class>
-		<load-on-startup>1</load-on-startup>
-	</servlet>
-	<servlet-mapping>
-		<servlet-name>postgres-update</servlet-name>
-		<url-pattern>/postgres-update</url-pattern>
-	</servlet-mapping>
-	<servlet>
-		<servlet-name>postgres-fortunes</servlet-name>
-		<servlet-class>hello.PostgreFortunesServlet</servlet-class>
-		<load-on-startup>1</load-on-startup>
-	</servlet>
-	<servlet-mapping>
-		<servlet-name>postgres-fortunes</servlet-name>
-		<url-pattern>/postgres-fortunes</url-pattern>
-	</servlet-mapping>
-  <resource-env-ref>
-	<resource-env-ref-name>jdbc/hello_world</resource-env-ref-name>
-	<resource-env-ref-type>javax.sql.DataSource</resource-env-ref-type>
-  </resource-env-ref>
-  <resource-env-ref>
-	<resource-env-ref-name>jdbc/postgres_hello_world</resource-env-ref-name>
-	<resource-env-ref-type>javax.sql.DataSource</resource-env-ref-type>
-  </resource-env-ref>
 </web-app>