Browse Source

Merge pull request #1595 from jamming/master

Java: Add sabina configurations
Hamilton Turner 10 years ago
parent
commit
38777bc15c

+ 78 - 2
frameworks/Java/sabina/benchmark_config.json

@@ -8,8 +8,59 @@
       "fortune_url": "/fortune",
       "update_url": "/update?queries=",
       "plaintext_url": "/plaintext",
+
       "port": 5050,
-      "setup_file": "setup",
+      "setup_file": "undertow-mongodb",
+      "approach": "Realistic",
+      "classification": "Micro",
+      "database": "MongoDB",
+      "framework": "Sabina",
+      "language": "Java",
+      "orm": "Raw",
+      "platform": "Servlet",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "Sabina Undertow MongoDB",
+      "notes": "",
+      "versus": "servlet"
+    }
+  }, {
+    "undertow-mysql": {
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/query?queries=",
+      "fortune_url": "/fortune",
+      "update_url": "/update?queries=",
+      "plaintext_url": "/plaintext",
+
+      "port": 5050,
+      "setup_file": "undertow",
+      "approach": "Realistic",
+      "classification": "Micro",
+      "database": "MySQL",
+      "framework": "Sabina",
+      "language": "Java",
+      "orm": "Raw",
+      "platform": "Servlet",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "Sabina Undertow MySQL",
+      "notes": "",
+      "versus": "servlet"
+    }
+  }, {
+    "jetty-mysql": {
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/query?queries=",
+      "fortune_url": "/fortune",
+      "update_url": "/update?queries=",
+      "plaintext_url": "/plaintext",
+
+      "port": 5050,
+      "setup_file": "jetty",
       "approach": "Realistic",
       "classification": "Micro",
       "database": "MySQL",
@@ -20,7 +71,32 @@
       "webserver": "None",
       "os": "Linux",
       "database_os": "Linux",
-      "display_name": "Sabina",
+      "display_name": "Sabina Jetty MySQL",
+      "notes": "",
+      "versus": "servlet"
+    }
+  }, {
+    "jetty-mongodb": {
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/query?queries=",
+      "fortune_url": "/fortune",
+      "update_url": "/update?queries=",
+      "plaintext_url": "/plaintext",
+
+      "port": 5050,
+      "setup_file": "jetty-mongodb",
+      "approach": "Realistic",
+      "classification": "Micro",
+      "database": "MongoDB",
+      "framework": "Sabina",
+      "language": "Java",
+      "orm": "Raw",
+      "platform": "Servlet",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "Sabina Jetty MongoDB",
       "notes": "",
       "versus": "servlet"
     }

+ 3 - 0
frameworks/Java/sabina/jetty-mongodb.sh

@@ -0,0 +1,3 @@
+#!/bin/bash
+
+./setup.sh -Dsabina.backend=jetty -Dsabina.benchmark.repository=mongodb

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

@@ -0,0 +1,3 @@
+#!/bin/bash
+
+./setup.sh -Dsabina.backend=jetty -Dsabina.benchmark.repository=mysql

+ 6 - 1
frameworks/Java/sabina/pom.xml

@@ -36,7 +36,7 @@
 
         <db.host>localhost</db.host>
 
-        <sabina-version>1.1.1</sabina-version>
+        <sabina-version>1.3.0</sabina-version>
     </properties>
 
     <repositories>
@@ -92,6 +92,11 @@
             <artifactId>mysql-connector-java</artifactId>
             <version>5.1.28</version>
         </dependency>
+        <dependency>
+            <groupId>org.mongodb</groupId>
+            <artifactId>mongo-java-driver</artifactId>
+            <version>3.0.0</version>
+        </dependency>
 
         <dependency>
             <groupId>org.testng</groupId>

+ 1 - 1
frameworks/Java/sabina/setup.sh

@@ -4,4 +4,4 @@
 source $IROOT/java8.installed
 
 mvn clean package -DskipTests -Ddb.host=${DBHOST}
-${JAVA_HOME}/bin/java -jar target/sabina-1.0.0.jar &
+${JAVA_HOME}/bin/java $@ -jar target/sabina-1.0.0.jar

+ 59 - 134
frameworks/Java/sabina/src/main/java/sabina/benchmark/Application.java

@@ -20,39 +20,29 @@ import static sabina.Sabina.*;
 import static sabina.content.JsonContent.toJson;
 import static sabina.view.MustacheView.renderMustache;
 
-import com.mchange.v2.c3p0.ComboPooledDataSource;
 import sabina.Request;
+import sabina.server.MatcherFilter;
 
-import java.sql.*;
 import java.util.*;
 import java.util.Date;
-import java.util.concurrent.ThreadLocalRandom;
-
-import javax.sql.DataSource;
+import javax.servlet.FilterConfig;
+import javax.servlet.annotation.WebFilter;
 
 /**
  * .
  */
-final class Application {
-    private static final String SETTINGS_RESOURCE = "/server.properties";
-    private static final Properties SETTINGS = loadConfiguration ();
-
-    private static final String JDBC_URL = SETTINGS.getProperty ("mysql.uri")
-        .replace ("${db.host}", "localhost"); // TODO Move this to Gradle build
-    private static final DataSource DATA_SOURCE = createSessionFactory ();
-    private static final int DB_ROWS = 10000;
-
-    private static final boolean AUTOCOMMIT = getProperty ("sabina.benchmark.autocommit") != null;
-    private static final String SELECT_WORLD = "select * from world where id = ?";
-    private static final String UPDATE_WORLD = "update world set randomNumber = ? where id = ?";
-    private static final String SELECT_FORTUNES = "select * from fortune";
+@WebFilter ("/*")
+final class Application extends MatcherFilter {
+    static final String SETTINGS_RESOURCE = "/server.properties";
+    static final Repository REPOSITORY = loadRepository ();
+    static final int DB_ROWS = 10000;
 
     private static final String MESSAGE = "Hello, World!";
     private static final String CONTENT_TYPE_TEXT = "text/plain";
     private static final String CONTENT_TYPE_JSON = "application/json";
     private static final String QUERIES_PARAM = "queries";
 
-    private static Properties loadConfiguration () {
+    static Properties loadConfiguration () {
         try {
             Properties settings = new Properties ();
             settings.load (Class.class.getResourceAsStream (SETTINGS_RESOURCE));
@@ -63,21 +53,43 @@ final class Application {
         }
     }
 
-    private static DataSource createSessionFactory () {
+    static Repository loadRepository () {
+        switch (getProperty ("sabina.benchmark.repository", "mysql")) {
+            case "mongodb":
+                return new MongoDbRepository (loadConfiguration ());
+            case "mysql":
+            default:
+                return new MySqlRepository (loadConfiguration ());
+        }
+    }
+
+    private static Object getDb (Request it) {
         try {
-            ComboPooledDataSource dataSource = new ComboPooledDataSource ();
-            dataSource.setMinPoolSize (32);
-            dataSource.setMaxPoolSize (256);
-            dataSource.setCheckoutTimeout (1800);
-            dataSource.setMaxStatements (50);
-            dataSource.setJdbcUrl (JDBC_URL);
-            return dataSource;
+            final World[] worlds = REPOSITORY.getWorlds (getQueries (it), false);
+            it.response.type (CONTENT_TYPE_JSON);
+            return toJson (it.queryParams (QUERIES_PARAM) == null? worlds[0] : worlds);
         }
-        catch (Exception ex) {
-            throw new RuntimeException (ex);
+        catch (Exception e){
+            e.printStackTrace ();
+            throw e;
         }
     }
 
+    private static Object getFortunes (Request it) {
+        List<Fortune> fortunes = REPOSITORY.getFortunes ();
+        fortunes.add (new Fortune (0, "Additional fortune added at request time."));
+        fortunes.sort ((a, b) -> a.message.compareTo (b.message));
+
+        it.response.type ("text/html; charset=utf-8");
+        return renderMustache ("/fortunes.mustache", fortunes);
+    }
+
+    private static Object getUpdates (Request it) {
+        World[] worlds = REPOSITORY.getWorlds (getQueries (it), true);
+        it.response.type (CONTENT_TYPE_JSON);
+        return toJson (it.queryParams (QUERIES_PARAM) == null? worlds[0] : worlds);
+    }
+
     private static int getQueries (final Request request) {
         try {
             String parameter = request.queryParams (QUERIES_PARAM);
@@ -97,118 +109,22 @@ final class Application {
         }
     }
 
-    private static Object getJson (Request it) {
-        it.response.type (CONTENT_TYPE_JSON);
-        return toJson (new Message ());
-    }
-
-    private static Object getDb (Request it) {
-        final int queries = getQueries (it);
-        final World[] worlds = new World[queries];
-
-        try (final Connection con = DATA_SOURCE.getConnection ()) {
-            final Random random = ThreadLocalRandom.current ();
-            final PreparedStatement stmt = con.prepareStatement (SELECT_WORLD);
-
-            for (int ii = 0; ii < queries; ii++) {
-                stmt.setInt (1, random.nextInt (DB_ROWS) + 1);
-                final ResultSet rs = stmt.executeQuery ();
-                while (rs.next ())
-                    worlds[ii] = new World (rs.getInt (1), rs.getInt (2));
-            }
-        }
-        catch (SQLException e) {
-            e.printStackTrace ();
-        }
-
-        it.response.type (CONTENT_TYPE_JSON);
-        return toJson (it.queryParams (QUERIES_PARAM) == null? worlds[0] : worlds);
-    }
-
-    private static Object getFortunes (Request it) {
-        final List<Fortune> fortunes = new ArrayList<> ();
-
-        try (final Connection con = DATA_SOURCE.getConnection ()) {
-            final ResultSet rs = con.prepareStatement (SELECT_FORTUNES).executeQuery ();
-            while (rs.next ())
-                fortunes.add (new Fortune (rs.getInt (1), rs.getString (2)));
-        }
-        catch (SQLException e) {
-            e.printStackTrace ();
-        }
-
-        fortunes.add (new Fortune (0, "Additional fortune added at request time."));
-        fortunes.sort ((a, b) -> a.message.compareTo (b.message));
-
-        it.response.type ("text/html; charset=utf-8");
-        return renderMustache ("/fortunes.mustache", fortunes);
-    }
-
-    private static Object getUpdates (Request it) {
-        final int queries = getQueries (it);
-        final World[] worlds = new World[queries];
-
-        try (final Connection con = DATA_SOURCE.getConnection ()) {
-            con.setAutoCommit (AUTOCOMMIT);
-
-            final Random random = ThreadLocalRandom.current ();
-            final PreparedStatement stmtSelect = con.prepareStatement (SELECT_WORLD);
-            final PreparedStatement stmtUpdate = con.prepareStatement (UPDATE_WORLD);
-
-            for (int ii = 0; ii < queries; ii++) {
-                stmtSelect.setInt (1, random.nextInt (DB_ROWS) + 1);
-                final ResultSet rs = stmtSelect.executeQuery ();
-                while (rs.next ()) {
-                    worlds[ii] = new World (rs.getInt (1), rs.getInt (2));
-                    stmtUpdate.setInt (1, random.nextInt (DB_ROWS) + 1);
-                    stmtUpdate.setInt (2, worlds[ii].id);
-
-                    if (AUTOCOMMIT) {
-                        stmtUpdate.executeUpdate ();
-                    }
-                    else {
-                        stmtUpdate.addBatch ();
-                    }
-                }
-            }
-
-            if (!AUTOCOMMIT) {
-                int count = 0;
-                boolean retrying;
-
-                do {
-                    try {
-                        stmtUpdate.executeBatch ();
-                        retrying = false;
-                    }
-                    catch (BatchUpdateException e) {
-                        retrying = true;
-                    }
-                }
-                while (count++ < 10 && retrying);
-
-                con.commit ();
-            }
-        }
-        catch (SQLException e) {
-            e.printStackTrace ();
-        }
-
-        it.response.type (CONTENT_TYPE_JSON);
-        return toJson (it.queryParams (QUERIES_PARAM) == null? worlds[0] : worlds);
-    }
-
     private static Object getPlaintext (Request it) {
         it.response.type (CONTENT_TYPE_TEXT);
         return MESSAGE;
     }
 
+    private static Object getJson (Request it) {
+        it.response.type (CONTENT_TYPE_JSON);
+        return toJson (new Message ());
+    }
+
     private static void addCommonHeaders (Request it) {
         it.header ("Server", "Undertow/1.1.2");
-        it.response.raw ().addDateHeader ("Date", new Date ().getTime ());
+        it.response.addDateHeader ("Date", new Date ().getTime ());
     }
 
-    public static void main (String[] args) {
+    private static void routes () {
         get ("/json", Application::getJson);
         get ("/db", Application::getDb);
         get ("/query", Application::getDb);
@@ -216,9 +132,18 @@ final class Application {
         get ("/update", Application::getUpdates);
         get ("/plaintext", Application::getPlaintext);
         after (Application::addCommonHeaders);
+    }
 
-        host (SETTINGS.getProperty ("web.host"));
-        port (SETTINGS.getProperty ("web.port"));
+    public static void main (String[] args) {
+        routes ();
+
+        Properties settings = loadConfiguration ();
+        host (settings.getProperty ("web.host"));
+        port (settings.getProperty ("web.port"));
         start ();
     }
+
+    @Override protected void routes (FilterConfig filterConfig) {
+        routes ();
+    }
 }

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

@@ -14,11 +14,6 @@
 
 package sabina.benchmark;
 
-/**
- * TODO .
- *
- * @author jam
- */
 final class Fortune {
     final int id;
     final String message;

+ 91 - 0
frameworks/Java/sabina/src/main/java/sabina/benchmark/MongoDbRepository.java

@@ -0,0 +1,91 @@
+/*
+ * Copyright © 2015 Juan José Aguililla. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language governing permissions
+ * and limitations under the License.
+ */
+
+package sabina.benchmark;
+
+import static com.mongodb.client.model.Filters.eq;
+import static java.lang.Integer.parseInt;
+import static sabina.benchmark.Application.DB_ROWS;
+
+import java.util.*;
+import java.util.concurrent.ThreadLocalRandom;
+
+import com.mongodb.*;
+import com.mongodb.client.MongoCollection;
+import com.mongodb.client.MongoDatabase;
+import org.bson.Document;
+
+final class MongoDbRepository implements Repository {
+    private MongoCollection<Document> worldCollection;
+    private MongoCollection<Document> fortuneCollection;
+
+    MongoDbRepository (Properties settings) {
+        final int PORT = parseInt (settings.getProperty ("mongodb.port"));
+        final String HOST = settings.getProperty ("mongodb.host");
+        final String DATABASE = settings.getProperty ("mongodb.database");
+        final String WORLD = settings.getProperty ("mongodb.world.collection");
+        final String FORTUNE = settings.getProperty ("mongodb.fortune.collection");
+
+        MongoClient mongoClient = new MongoClient (HOST, PORT);
+        MongoDatabase db = mongoClient.getDatabase (DATABASE);
+        worldCollection = db.getCollection (WORLD);
+        fortuneCollection = db.getCollection (FORTUNE);
+    }
+
+    @Override public List<Fortune> getFortunes () {
+        List<Fortune> fortunes = new ArrayList<> ();
+
+        fortuneCollection.find ().forEach ((Block<Document>)doc ->
+            fortunes.add (new Fortune (doc.get ("_id", Double.class).intValue (), (String)doc.get
+                ("message")))
+        );
+
+        return fortunes;
+    }
+
+    @Override public World[] getWorlds (int queries, boolean update) {
+        final World[] worlds = new World[queries];
+        final Random random = ThreadLocalRandom.current ();
+
+        for (int ii = 0; ii < queries; ii++) {
+            int id = random.nextInt (DB_ROWS) + 1;
+            worlds[ii] = update? updateWorld (id, random.nextInt (DB_ROWS) + 1) : findWorld (id);
+        }
+
+        return worlds;
+    }
+
+    private World findWorld (int id) {
+        return createWorld (worldCollection.find(eq ("_id", (double)id)).first ());
+    }
+
+    private World createWorld (Document world) {
+        try {
+            return new World (world.get ("_id", Double.class).intValue (), world.get
+                ("randomNumber", Double.class).intValue ());
+        }
+        catch (ClassCastException e) {
+            return new World (world.get ("_id", Double.class).intValue (), world.get
+                ("randomNumber", Integer.class));
+        }
+    }
+
+    public World updateWorld (int id, int random) {
+        Document newWorld = new Document ("_id", (double)id).append ("randomNumber", (double)
+            random);
+        worldCollection.replaceOne (eq ("_id", (double)id), newWorld);
+
+        return new World (id, random);
+    }
+}

+ 139 - 0
frameworks/Java/sabina/src/main/java/sabina/benchmark/MySqlRepository.java

@@ -0,0 +1,139 @@
+/*
+ * Copyright © 2015 Juan José Aguililla. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language governing permissions
+ * and limitations under the License.
+ */
+
+package sabina.benchmark;
+
+import static java.lang.System.getProperty;
+import static sabina.benchmark.Application.DB_ROWS;
+
+import java.sql.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+import java.util.Random;
+import java.util.concurrent.ThreadLocalRandom;
+
+import javax.sql.DataSource;
+
+import com.mchange.v2.c3p0.ComboPooledDataSource;
+
+final class MySqlRepository implements Repository {
+    private static final boolean AUTOCOMMIT = getProperty ("sabina.benchmark.autocommit") != null;
+    private static final String SELECT_WORLD = "select * from world where id = ?";
+    private static final String UPDATE_WORLD = "update world set randomNumber = ? where id = ?";
+    private static final String SELECT_FORTUNES = "select * from fortune";
+
+    private final DataSource DATA_SOURCE;
+
+    MySqlRepository (Properties settings) {
+        final String jdbcUrl = settings.getProperty ("mysql.uri");
+        DATA_SOURCE = createSessionFactory (jdbcUrl);
+    }
+
+    private DataSource createSessionFactory (String jdbcUrl) {
+        try {
+            ComboPooledDataSource dataSource = new ComboPooledDataSource ();
+            dataSource.setMinPoolSize (32);
+            dataSource.setMaxPoolSize (256);
+            dataSource.setCheckoutTimeout (1800);
+            dataSource.setMaxStatements (50);
+            dataSource.setJdbcUrl (jdbcUrl);
+            return dataSource;
+        }
+        catch (Exception ex) {
+            throw new RuntimeException (ex);
+        }
+    }
+
+    private void commitUpdate (Connection con, PreparedStatement stmtUpdate)
+        throws SQLException {
+        int count = 0;
+        boolean retrying;
+
+        do {
+            try {
+                stmtUpdate.executeBatch ();
+                retrying = false;
+            }
+            catch (BatchUpdateException e) {
+                retrying = true;
+            }
+        }
+        while (count++ < 10 && retrying);
+
+        con.commit ();
+    }
+
+    private void updateWorld (World world, PreparedStatement stmtUpdate)
+        throws SQLException {
+        stmtUpdate.setInt (1, world.randomNumber);
+        stmtUpdate.setInt (2, world.id);
+
+        if (AUTOCOMMIT) {
+            stmtUpdate.executeUpdate ();
+        }
+        else {
+            stmtUpdate.addBatch ();
+        }
+    }
+
+    @Override public List<Fortune> getFortunes () {
+        final List<Fortune> fortunes = new ArrayList<> ();
+
+        try (final Connection con = DATA_SOURCE.getConnection ()) {
+            final ResultSet rs = con.prepareStatement (SELECT_FORTUNES).executeQuery ();
+            while (rs.next ())
+                fortunes.add (new Fortune (rs.getInt (1), rs.getString (2)));
+        }
+        catch (SQLException e) {
+            e.printStackTrace ();
+        }
+
+        return fortunes;
+    }
+
+    @Override public World[] getWorlds (int queries, boolean update) {
+        final World[] worlds = new World[queries];
+
+        try (final Connection con = DATA_SOURCE.getConnection ()) {
+            if (update)
+                con.setAutoCommit (AUTOCOMMIT);
+
+            final Random random = ThreadLocalRandom.current ();
+            final PreparedStatement stmtSelect = con.prepareStatement (SELECT_WORLD);
+            final PreparedStatement stmtUpdate = update? con.prepareStatement (UPDATE_WORLD) : null;
+
+            for (int ii = 0; ii < queries; ii++) {
+                stmtSelect.setInt (1, random.nextInt (DB_ROWS) + 1);
+                final ResultSet rs = stmtSelect.executeQuery ();
+                while (rs.next ()) {
+                    worlds[ii] = new World (rs.getInt (1), rs.getInt (2));
+
+                    if (update) {
+                        worlds[ii] = new World (worlds[ii].id, random.nextInt (DB_ROWS) + 1);
+                        updateWorld (worlds[ii], stmtUpdate);
+                    }
+                }
+            }
+
+            if (update && !AUTOCOMMIT)
+                commitUpdate (con, stmtUpdate);
+        }
+        catch (SQLException e) {
+            e.printStackTrace ();
+        }
+
+        return worlds;
+    }
+}

+ 22 - 0
frameworks/Java/sabina/src/main/java/sabina/benchmark/Repository.java

@@ -0,0 +1,22 @@
+/*
+ * Copyright © 2015 Juan José Aguililla. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language governing permissions
+ * and limitations under the License.
+ */
+
+package sabina.benchmark;
+
+import java.util.List;
+
+interface Repository {
+    List<Fortune> getFortunes ();
+    World[] getWorlds (int queries, boolean update);
+}

+ 5 - 2
frameworks/Java/sabina/src/main/resources/server.properties

@@ -15,8 +15,11 @@
 web.port = 5050
 web.host = 0.0.0.0
 
-mongodb.uri = ${db.host}:27017
-mongodb.name = hello_world
+mongodb.host = ${db.host}
+mongodb.port = 27017
+mongodb.database = hello_world
+mongodb.world.collection = world
+mongodb.fortune.collection = fortune
 
 mysql.uri = jdbc:mysql://${db.host}:3306/hello_world?\
 user=benchmarkdbuser&\

+ 13 - 28
frameworks/Java/sabina/src/test/java/sabina/benchmark/ApplicationTest.java

@@ -16,7 +16,6 @@ package sabina.benchmark;
 
 import static org.apache.http.client.fluent.Request.Get;
 import static org.testng.AssertJUnit.*;
-import static sabina.benchmark.Application.main;
 import static sabina.Sabina.stop;
 
 import java.io.IOException;
@@ -39,37 +38,13 @@ import org.testng.annotations.Test;
  * <p>TODO Change assert's order
  */
 public final class ApplicationTest {
-    private static final int THREADS = 16, EXECUTIONS = 32, WARM_UP = 32;
+    private static final int THREADS = 1, EXECUTIONS = 1;
 
     private static final String ENDPOINT = "http://localhost:5050";
     private static final Gson GSON = new Gson ();
 
     @BeforeClass public static void setup () {
-        main (null);
-    }
-
-    @BeforeClass public void warm_up () throws IOException {
-        for (int ii = 0; ii < WARM_UP; ii++) {
-            json ();
-            plaintext ();
-            no_query_parameter ();
-            empty_query_parameter ();
-            text_query_parameter ();
-            zero_queries ();
-            one_thousand_queries ();
-            one_query ();
-            ten_queries ();
-            five_hundred_queries ();
-            fortunes ();
-            no_updates_parameter ();
-            empty_updates_parameter ();
-            text_updates_parameter ();
-            zero_updates ();
-            one_thousand_updates ();
-            one_update ();
-            ten_updates ();
-            five_hundred_updates ();
-        }
+        Application.main (null);
     }
 
     @AfterClass public static void close () {
@@ -134,6 +109,11 @@ public final class ApplicationTest {
         checkDbRequest ("/query?queries=10", 10);
     }
 
+    @Test(threadPoolSize = THREADS, invocationCount = EXECUTIONS)
+    public void one_hundred_queries () throws IOException {
+        checkDbRequest ("/query?queries=100", 100);
+    }
+
     @Test(threadPoolSize = THREADS, invocationCount = EXECUTIONS)
     public void five_hundred_queries () throws IOException {
         checkDbRequest ("/query?queries=500", 500);
@@ -192,6 +172,11 @@ public final class ApplicationTest {
         checkDbRequest ("/update?queries=10", 10);
     }
 
+    @Test(threadPoolSize = THREADS, invocationCount = EXECUTIONS)
+    public void one_hundred_updates () throws IOException {
+        checkDbRequest ("/update?queries=100", 100);
+    }
+
     @Test(threadPoolSize = THREADS, invocationCount = EXECUTIONS)
     public void five_hundred_updates () throws IOException {
         checkDbRequest ("/update?queries=500", 500);
@@ -218,7 +203,7 @@ public final class ApplicationTest {
         assertTrue (res.getFirstHeader ("Server") != null);
         assertTrue (res.getFirstHeader ("Date") != null);
         assertEquals (content.length (), res.getEntity ().getContentLength ());
-        assertEquals (contentType, res.getEntity ().getContentType ().getValue ());
+        assertTrue (res.getEntity ().getContentType ().getValue ().contains (contentType));
     }
 
     private void checkResultItems (String result, int size) {

+ 3 - 0
frameworks/Java/sabina/undertow-mongodb.sh

@@ -0,0 +1,3 @@
+#!/bin/bash
+
+./setup.sh -Dsabina.backend=undertow -Dsabina.benchmark.repository=mongodb

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

@@ -0,0 +1,3 @@
+#!/bin/bash
+
+./setup.sh -Dsabina.backend=undertow -Dsabina.benchmark.repository=mysql