Browse Source

Added Servlet implementation of Fortunes test.

Brian Hauer 12 years ago
parent
commit
f77b0870f7

+ 8 - 1
config/create-fortunes.sql

@@ -1,4 +1,11 @@
-DELETE FROM fortune;
+DROP TABLE IF EXISTS Fortune;
+CREATE TABLE  Fortune (
+  id int(10) unsigned NOT NULL auto_increment,
+  message varchar(2048) CHARACTER SET 'utf8' NOT NULL,
+  PRIMARY KEY  (id)
+)
+ENGINE=INNODB;
+
 INSERT INTO fortune (message) VALUES ('fortune: No such file or directory');
 INSERT INTO fortune (message) VALUES ('fortune: No such file or directory');
 INSERT INTO fortune (message) VALUES ('A computer scientist is someone who fixes things that aren''t broken.');
 INSERT INTO fortune (message) VALUES ('A computer scientist is someone who fixes things that aren''t broken.');
 INSERT INTO fortune (message) VALUES ('After enough decimal places, nobody gives a damn.');
 INSERT INTO fortune (message) VALUES ('After enough decimal places, nobody gives a damn.');

+ 1 - 1
gemini/.project

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <?xml version="1.0" encoding="UTF-8"?>
 <projectDescription>
 <projectDescription>
-	<name>GeminiHello</name>
+	<name>FrameworkBenchmarks-Gemini</name>
 	<comment></comment>
 	<comment></comment>
 	<projects>
 	<projects>
 		<project>TechEmpower</project>
 		<project>TechEmpower</project>

+ 9 - 6
servlet/.classpath

@@ -1,10 +1,13 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
 <classpath>
-	<classpathentry kind="src" path="src"/>
-	<classpathentry kind="lib" path="docroot/WEB-INF/lib/jackson-annotations-2.1.1.jar"/>
-	<classpathentry kind="lib" path="docroot/WEB-INF/lib/jackson-core-2.1.1.jar"/>
-	<classpathentry kind="lib" path="docroot/WEB-INF/lib/jackson-databind-2.1.1.jar"/>
+	<classpathentry including="**/*.java" kind="src" path="src/main/java"/>
+	<classpathentry kind="var" path="M2_REPO/javax/inject/javax.inject/1/javax.inject-1.jar"/>
+	<classpathentry kind="var" path="M2_REPO/javax/servlet/servlet-api/2.5/servlet-api-2.5.jar"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
-	<classpathentry kind="var" path="Resin4"/>
-	<classpathentry kind="output" path="docroot/WEB-INF/classes"/>
+	<classpathentry kind="var" path="M2_REPO/mysql/mysql-connector-java/5.1.23/mysql-connector-java-5.1.23.jar"/>
+	<classpathentry kind="var" path="M2_REPO/com/fasterxml/jackson/core/jackson-databind/2.1.2/jackson-databind-2.1.2.jar"/>
+	<classpathentry kind="var" path="M2_REPO/com/fasterxml/jackson/core/jackson-annotations/2.1.1/jackson-annotations-2.1.1.jar"/>
+	<classpathentry kind="var" path="M2_REPO/com/fasterxml/jackson/core/jackson-core/2.1.1/jackson-core-2.1.1.jar"/>
+	<classpathentry kind="var" path="M2_REPO/org/apache/commons/commons-lang3/3.1/commons-lang3-3.1.jar"/>
+	<classpathentry kind="output" path="src/main/webapp/WEB-INF/classes"/>
 </classpath>
 </classpath>

+ 3 - 0
servlet/.gitignore

@@ -0,0 +1,3 @@
+lib/
+work/
+*.bat

+ 12 - 15
servlet/.project

@@ -1,17 +1,14 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <?xml version="1.0" encoding="UTF-8"?>
 <projectDescription>
 <projectDescription>
-	<name>ServletHello</name>
-	<comment></comment>
-	<projects>
-	</projects>
-	<buildSpec>
-		<buildCommand>
-			<name>org.eclipse.jdt.core.javabuilder</name>
-			<arguments>
-			</arguments>
-		</buildCommand>
-	</buildSpec>
-	<natures>
-		<nature>org.eclipse.jdt.core.javanature</nature>
-	</natures>
-</projectDescription>
+  <name>world</name>
+  <comment>NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse.</comment>
+  <projects/>
+  <buildSpec>
+    <buildCommand>
+      <name>org.eclipse.jdt.core.javabuilder</name>
+    </buildCommand>
+  </buildSpec>
+  <natures>
+    <nature>org.eclipse.jdt.core.javanature</nature>
+  </natures>
+</projectDescription>

+ 5 - 0
servlet/.settings/org.eclipse.jdt.core.prefs

@@ -0,0 +1,5 @@
+#Thu Apr 11 13:42:30 PDT 2013
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.source=1.7
+org.eclipse.jdt.core.compiler.compliance=1.7

+ 9 - 2
servlet/pom.xml

@@ -22,7 +22,7 @@
             <artifactId>jackson-databind</artifactId>
             <artifactId>jackson-databind</artifactId>
             <version>2.1.2</version>
             <version>2.1.2</version>
         </dependency>
         </dependency>
- 
+
         <!-- @Inject -->
         <!-- @Inject -->
         <dependency>
         <dependency>
             <groupId>javax.inject</groupId>
             <groupId>javax.inject</groupId>
@@ -37,7 +37,14 @@
             <version>2.5</version>
             <version>2.5</version>
             <scope>provided</scope>
             <scope>provided</scope>
         </dependency>
         </dependency>
- 
+
+        <!-- Apache Commons Lang -->
+        <dependency>
+          	<groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+            <version>3.1</version>
+        </dependency>
+
     </dependencies>
     </dependencies>
 
 
     <build>
     <build>

+ 30 - 0
servlet/src/main/java/hello/Common.java

@@ -0,0 +1,30 @@
+package hello;
+
+import org.apache.commons.lang3.*;
+
+import com.fasterxml.jackson.databind.*;
+
+/**
+ * Some common functionality and constants used by the Servlet tests.
+ */
+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_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);        
+  }
+  
+}

+ 10 - 19
servlet/src/main/java/hello/DbPoolServlet.java

@@ -10,37 +10,28 @@ import javax.servlet.*;
 import javax.servlet.http.*;
 import javax.servlet.http.*;
 import javax.sql.*;
 import javax.sql.*;
 
 
-import com.fasterxml.jackson.databind.*;
-
 /**
 /**
- * Database connectivity (with a Servlet-container managed pool) test
+ * Database connectivity (with a Servlet-container managed pool) test.
  */
  */
 @SuppressWarnings("serial")
 @SuppressWarnings("serial")
 public class DbPoolServlet extends HttpServlet
 public class DbPoolServlet extends HttpServlet
 {
 {
-  // Constants for setting the content type.
-  private static final String HEADER_CONTENT_TYPE    = "Content-Type";
-  private static final String CONTENT_TYPE_JSON      = "application/json";
-  
+  // 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/hello_world")
   @Resource(name="jdbc/hello_world")
   private DataSource mysqlDataSource;
   private DataSource mysqlDataSource;
-
-  // Jackson encoder, reused for each response.
-  private final ObjectMapper mapper = new ObjectMapper();
-  
-  // Database details.
-  private static final String DB_QUERY               = "SELECT * FROM World WHERE id = ?";
-  private static final int    DB_ROWS                = 10000;
-  
+    
   @Override
   @Override
   protected void doGet(HttpServletRequest req, HttpServletResponse res)
   protected void doGet(HttpServletRequest req, HttpServletResponse res)
       throws ServletException, IOException
       throws ServletException, IOException
   {
   {
     // Set content type to JSON
     // Set content type to JSON
-    res.setHeader(HEADER_CONTENT_TYPE, CONTENT_TYPE_JSON);
+    res.setHeader(Common.HEADER_CONTENT_TYPE, Common.CONTENT_TYPE_JSON);
 
 
-    // Select the MySQL source by default, but allow the option of selecting
-    // Postgres by providing a parameter named "postgres".
+    // Reference the data source.
     final DataSource source = mysqlDataSource;
     final DataSource source = mysqlDataSource;
     
     
     // Get the count of queries to run.
     // Get the count of queries to run.
@@ -97,7 +88,7 @@ public class DbPoolServlet extends HttpServlet
     // Write JSON encoded message to the response.
     // Write JSON encoded message to the response.
     try
     try
     {
     {
-      mapper.writeValue(res.getOutputStream(), worlds);
+      Common.MAPPER.writeValue(res.getOutputStream(), worlds);
     }
     }
     catch (IOException ioe) 
     catch (IOException ioe) 
     {
     {

+ 38 - 0
servlet/src/main/java/hello/Fortune.java

@@ -0,0 +1,38 @@
+package hello;
+
+/**
+ * Simple Fortune cookie entity.
+ */
+public class Fortune
+  implements Comparable<Fortune>
+{
+
+  private final int    id;
+  private final String message;
+  
+  public Fortune(int id, String message)
+  {
+    this.id = id;
+    this.message = message;
+  }
+  
+  public int getId()
+  {
+    return this.id;
+  }
+  
+  public String getMessage()
+  {
+    return this.message;
+  }      
+
+  /**
+   * For our purposes, Fortunes sort by their message text. 
+   */
+  @Override
+  public int compareTo(Fortune other)
+  {
+    return getMessage().compareTo(other.getMessage());
+  }
+  
+}

+ 69 - 0
servlet/src/main/java/hello/FortunesServlet.java

@@ -0,0 +1,69 @@
+package hello;
+
+import java.io.*;
+import java.sql.*;
+import java.util.*;
+
+import javax.annotation.*;
+import javax.servlet.*;
+import javax.servlet.http.*;
+import javax.sql.*;
+
+/**
+ * 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";
+
+  // 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_HTML);
+
+    // Reference the data source.
+    final DataSource source = mysqlDataSource;
+
+    List<Fortune> fortunes = new ArrayList<>();
+    
+    try (Connection conn = source.getConnection())
+    {
+      try (PreparedStatement statement = conn.prepareStatement(DB_QUERY, 
+          ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY))
+      {
+        try (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);
+  }
+}

+ 3 - 10
servlet/src/main/java/hello/JsonServlet.java

@@ -5,20 +5,12 @@ import java.io.*;
 import javax.servlet.*;
 import javax.servlet.*;
 import javax.servlet.http.*;
 import javax.servlet.http.*;
 
 
-import com.fasterxml.jackson.databind.*;
-
 /**
 /**
  * JSON Encoding Test
  * JSON Encoding Test
  */
  */
 @SuppressWarnings("serial")
 @SuppressWarnings("serial")
 public class JsonServlet extends HttpServlet
 public class JsonServlet extends HttpServlet
 {
 {
-  // Constants for setting the content type.
-  private static final String HEADER_CONTENT_TYPE    = "Content-Type";
-  private static final String CONTENT_TYPE_JSON      = "application/json";
-
-  // Jackson encoder, reused for each response.
-  private final ObjectMapper mapper = new ObjectMapper();
 
 
   // Response message class.
   // Response message class.
   public static class HelloMessage {
   public static class HelloMessage {
@@ -30,16 +22,17 @@ public class JsonServlet extends HttpServlet
       throws ServletException, IOException
       throws ServletException, IOException
   {
   {
     // Set content type to JSON
     // Set content type to JSON
-    res.setHeader(HEADER_CONTENT_TYPE, CONTENT_TYPE_JSON);
+    res.setHeader(Common.HEADER_CONTENT_TYPE, Common.CONTENT_TYPE_JSON);
 
 
     // Write JSON encoded message to the response.
     // Write JSON encoded message to the response.
     try
     try
     {
     {
-      mapper.writeValue(res.getOutputStream(), new HelloMessage());
+      Common.MAPPER.writeValue(res.getOutputStream(), new HelloMessage());
     }
     }
     catch (IOException ioe) 
     catch (IOException ioe) 
     {
     {
       // do nothing
       // do nothing
     }
     }
   }
   }
+  
 }
 }

+ 24 - 0
servlet/src/main/webapp/WEB-INF/jsp/fortunes.jsp

@@ -0,0 +1,24 @@
+<%@ page import="hello.*,
+                 java.util.*" %><%@ page session="false" %><%
+
+List<Fortune> fortunes = (List)request.getAttribute("fortunes");
+
+%>
+<!DOCTYPE html>
+<html>
+<head>
+<title>Fortunes</title>
+</head>
+<body>
+<table>
+<tr>
+<th>id</th>
+<th>message</th>
+</tr>
+<% for (Fortune fortune : fortunes) { %><tr>
+<td><%= fortune.getId() %></td>
+<td><%= Common.render(fortune.getMessage()) %></td>
+</tr>
+<% } %>
+</table></body>
+</html>

+ 1 - 1
servlet/src/main/webapp/WEB-INF/resin-web.xml

@@ -3,7 +3,7 @@
 <database jndi-name='jdbc/hello_world'>
 <database jndi-name='jdbc/hello_world'>
   <driver>
   <driver>
     <type>com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource</type>
     <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</url>
+    <url>jdbc:mysql://172.16.98.98: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</url>
     <user>benchmarkdbuser</user>
     <user>benchmarkdbuser</user>
     <password>benchmarkdbpass</password>
     <password>benchmarkdbpass</password>
     <useUnicode/>
     <useUnicode/>

+ 6 - 0
servlet/src/main/webapp/WEB-INF/web.xml

@@ -11,4 +11,10 @@
     <load-on-startup/>
     <load-on-startup/>
   </servlet>
   </servlet>
   <servlet-mapping url-regexp='^/db$' servlet-name='db'/>
   <servlet-mapping url-regexp='^/db$' servlet-name='db'/>
+  <servlet>
+    <servlet-name>fortunes</servlet-name>
+    <servlet-class>hello.FortunesServlet</servlet-class>
+    <load-on-startup/>
+  </servlet>
+  <servlet-mapping url-regexp='^/fortunes$' servlet-name='fortunes'/>
 </web-app>
 </web-app>