Browse Source

[ci fw-only Java/restexpress] Refresh RestExpress (#4689)

* Add multiple queries for MongoDB and MySQL. Add exception handling for the DB resources.

* Fix Docker files

* Update Docker files to actually work

* Add logic to initilize only MySQL or MongoDB endpoints. Add separate config files and rename them in the Docker file

* Try to make Netty happy

* Try SNAPSHOT dependencies

* Fix failing compilation

* Disable response compression

* Add required headers

* Add nasty patch of copy-paste-modify base classes to fix the failing start of the MongoDB variant

* Move JSON controller to MongoDB test case. Enable plaintext controller

* Get initialization of controllers in the correct variant. Shorten endpoint URLs. Update README.md

* Update plaintext controller return plaintext

* Fix README.md links

* Fix README.md by removing unrelated sentense
Radoslav Petrov 6 years ago
parent
commit
c422e85df8
23 changed files with 778 additions and 319 deletions
  1. 31 22
      frameworks/Java/restexpress/README.md
  2. 6 6
      frameworks/Java/restexpress/benchmark_config.json
  3. 52 6
      frameworks/Java/restexpress/pom.xml
  4. 6 7
      frameworks/Java/restexpress/restexpress-mysql-raw.dockerfile
  5. 6 7
      frameworks/Java/restexpress/restexpress.dockerfile
  6. 39 46
      frameworks/Java/restexpress/src/main/java/hello/Main.java
  7. 23 0
      frameworks/Java/restexpress/src/main/java/hello/RequiredResponseHeaders.java
  8. 45 37
      frameworks/Java/restexpress/src/main/java/hello/config/Configuration.java
  9. 5 0
      frameworks/Java/restexpress/src/main/java/hello/config/Database.java
  10. 12 23
      frameworks/Java/restexpress/src/main/java/hello/config/MongoConfig.java
  11. 51 23
      frameworks/Java/restexpress/src/main/java/hello/config/MysqlConfig.java
  12. 7 9
      frameworks/Java/restexpress/src/main/java/hello/controller/JsonController.java
  13. 9 8
      frameworks/Java/restexpress/src/main/java/hello/controller/MongodbController.java
  14. 9 9
      frameworks/Java/restexpress/src/main/java/hello/controller/MysqlController.java
  15. 3 3
      frameworks/Java/restexpress/src/main/java/hello/controller/PlaintextController.java
  16. 14 17
      frameworks/Java/restexpress/src/main/java/hello/controller/QueriesMongodbController.java
  17. 19 24
      frameworks/Java/restexpress/src/main/java/hello/controller/QueriesMysqlController.java
  18. 392 0
      frameworks/Java/restexpress/src/main/java/hello/controller/persistence/MongodbRepository.java
  19. 23 14
      frameworks/Java/restexpress/src/main/java/hello/controller/persistence/WorldsMongodbRepository.java
  20. 16 20
      frameworks/Java/restexpress/src/main/java/hello/domain/World.java
  21. 6 0
      frameworks/Java/restexpress/src/main/resources/config/dev/mongodb-environment.properties
  22. 4 4
      frameworks/Java/restexpress/src/main/resources/config/dev/mysql-environment.properties
  23. 0 34
      frameworks/Java/restexpress/zip-with-dependencies.xml

+ 31 - 22
frameworks/Java/restexpress/README.md

@@ -1,35 +1,44 @@
-#RestExpress Benchmarking Test
+# RestExpress Benchmarking Test
 
-This is the Java RestExpress portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+[RestExpress](http://www.restexpress.org/) - composes tools to form a lightweight, minimalist Java framework for quickly creating RESTful microservices.
 
-### 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).
+Test implementations with MongoDB and MySQL as a backing datastore. MongoDB is using Morphia framework for object persistance.
 
-* [JSON test source](src/main/java/hello/JsonServlet.java)
+### Test sources
 
-### Data-Store/Database Mapping Test
-* [DB test source](src/main/java/hello/DBServlet.java)
+Which `Controllers` will be instantiated and wired is determined from the existense of the MongoDB or MySQL connection string.
 
-## Infrastructure Software Versions
-The tests were run with:
+**Important** 
+ * The build is using a 0.12.0-SNAPSHOT version of the RestExpress. There were problems at startup with the bundled Netty in the 0.11.3 version;
+ * The MongoDB repository class is copy-pasted and new argument is introduced to get around the mandatory initialization of MongoDB indexes and collection caps.
 
-* [Java OpenJDK 1.7.0_09](http://openjdk.java.net/)
-* [Netty 3.6.2](http://netty.io)
-* [Jackson 2.1.4](http://wiki.fasterxml.com/JacksonHome)
-* [Morphia 1.2.2](https://github.com/jmkgreen/morphia)
-* [RepoExpress 0.3.2](https://github.com/RestExpress/RepoExpress)
-* [MySQL 5.5.29](https://dev.mysql.com/)
+### MongoDB
+ * [Plaintext](src/main/java/hello/controller/PlaintextController.java)
+ * [JSON](src/main/java/hello/controller/JsonController.java)
+ * [DB](src/main/java/hello/controller/MongodbController.java)
+ * [Queries](src/main/java/hello/controller/QueriesMongodbController.java)
 
-## Test URLs
-### JSON Encoding Test
+### MySQL
+
+ * [DB](src/main/java/hello/controller/MysqlController.java)
+ * [Queries](src/main/java/hello/controller/QueriesMysqlController.java)
 
-http://localhost:8080/restexpress/json
+## Software Versions
 
-### MySQL Database Mapping Test
+The tests were run with:
+
+ * [Oracle Java 10](https://www.oracle.com/java/)
+ * [MySQL 5.7](http://www.mysql.com/)
+ * [MongoDB](http://www.mongodb.com/)
+ * [Morphia](https://morphia.dev/)
 
-http://localhost:8080/restexpress/mysql?queries=5
+Please check the versions in the install and build scripts of TFB project.
 
-### MongoDB Database Mapping Test
+## Test URLs
 
-http://localhost:8080/restexpress/mongodb?queries=5
+All implementations use the same URLs.
 
+ * Plaintext - `http://localhost:8080/plaintext`
+ * JSON - `http://localhost:8080/json`
+ * DB - `http://localhost:8080/db`
+ * Queries - `http://localhost:8080/query?queries=`

+ 6 - 6
frameworks/Java/restexpress/benchmark_config.json

@@ -2,10 +2,10 @@
   "framework": "restexpress",
   "tests": [{
     "default": {
-      "json_url": "/restexpress/json",
-      "plaintext_url": "/restexpress/plaintext",
-      "db_url": "/restexpress/mongo/db",
-      "query_url": "/restexpress/mongo/query?queries=",
+      "json_url": "/json",
+      "plaintext_url": "/plaintext",
+      "db_url": "/db",
+      "query_url": "/query?queries=",
       "port": 8080,
       "approach": "Realistic",
       "classification": "Micro",
@@ -23,8 +23,8 @@
       "versus": "netty"
     },
     "mysql-raw": {
-      "db_url": "/restexpress/mysql/db",
-      "query_url": "/restexpress/mysql/query?queries=",
+      "db_url": "/db",
+      "query_url": "/query?queries=",
       "port": 8080,
       "approach": "Realistic",
       "classification": "Micro",

+ 52 - 6
frameworks/Java/restexpress/pom.xml

@@ -26,12 +26,17 @@
 		<dependency>
 			<groupId>com.strategicgains</groupId>
 			<artifactId>RestExpress</artifactId>
-			<version>0.9.2</version>
+			<version>0.12.0-SNAPSHOT</version>
 		</dependency>
 		<dependency>
 			<groupId>com.strategicgains.repoexpress</groupId>
 			<artifactId>repoexpress-mongodb</artifactId>
-			<version>0.3.2</version>
+			<version>0.4.8</version>
+		</dependency>
+		<dependency>
+			<groupId>commons-dbcp</groupId>
+			<artifactId>commons-dbcp</artifactId>
+			<version>1.4</version>
 		</dependency>
 		<dependency>
 			<groupId>mysql</groupId>
@@ -40,6 +45,27 @@
 		</dependency>
 	</dependencies>
 
+	<profiles>
+		<profile>
+			<id>allow-snapshots</id>
+			<activation>
+				<activeByDefault>true</activeByDefault>
+			</activation>
+			<repositories>
+				<repository>
+					<id>sonatype-snapshots-repo</id>
+					<url>https://oss.sonatype.org/content/repositories/snapshots</url>
+					<releases>
+						<enabled>false</enabled>
+					</releases>
+					<snapshots>
+						<enabled>true</enabled>
+					</snapshots>
+				</repository>
+			</repositories>
+		</profile>
+	</profiles>
+  
 	<build>
 		<defaultGoal>package</defaultGoal>
 
@@ -72,13 +98,33 @@
 					</archive>
 				</configuration>
 			</plugin>
-			<plugin>
+						<plugin>
 				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-assembly-plugin</artifactId>
-				<version>2.4</version>
+				<artifactId>maven-shade-plugin</artifactId>
+				<version>2.4.1</version>
 				<configuration>
-					<descriptor>zip-with-dependencies.xml</descriptor>
+					<createDependencyReducedPom>false</createDependencyReducedPom>
+					<filters>
+						<filter>
+							<artifact>*:*</artifact>
+						</filter>
+					</filters>
 				</configuration>
+				<executions>
+					<execution>
+						<phase>package</phase>
+						<goals>
+							<goal>shade</goal>
+						</goals>
+						<configuration>
+							<transformers>
+								<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+									<mainClass>hello.Main</mainClass>
+								</transformer>
+							</transformers>
+						</configuration>
+					</execution>
+				</executions>
 			</plugin>
 		</plugins>
 	</build>

+ 6 - 7
frameworks/Java/restexpress/restexpress-mysql-raw.dockerfile

@@ -1,12 +1,11 @@
 FROM maven:3.5.3-jdk-10 as maven
 WORKDIR /restexpress
-COPY config config
 COPY src src
+COPY src/main/resources/config/dev/mysql-environment.properties src/main/resources/config/dev/environment.properties
 COPY pom.xml pom.xml
-COPY zip-with-dependencies.xml zip-with-dependencies.xml
 RUN mvn package -q
-RUN mvn assembly:single -q
-WORKDIR target
-RUN unzip -q world-1.0-SNAPSHOT-zip-with-dependencies.zip
-WORKDIR world-1.0-SNAPSHOT
-CMD ["java", "-jar", "world-1.0-SNAPSHOT.jar"]
+
+FROM openjdk:10-jre-slim
+WORKDIR /restexpress
+COPY --from=maven /restexpress/target/world-1.0-SNAPSHOT.jar app.jar
+CMD ["java", "-jar", "app.jar"]

+ 6 - 7
frameworks/Java/restexpress/restexpress.dockerfile

@@ -1,12 +1,11 @@
 FROM maven:3.5.3-jdk-10 as maven
 WORKDIR /restexpress
-COPY config config
 COPY src src
+COPY src/main/resources/config/dev/mongodb-environment.properties src/main/resources/config/dev/environment.properties
 COPY pom.xml pom.xml
-COPY zip-with-dependencies.xml zip-with-dependencies.xml
 RUN mvn package -q
-RUN mvn assembly:single -q
-WORKDIR target
-RUN unzip -q world-1.0-SNAPSHOT-zip-with-dependencies.zip
-WORKDIR world-1.0-SNAPSHOT
-CMD ["java", "-jar", "world-1.0-SNAPSHOT.jar"]
+
+FROM openjdk:10-jre-slim
+WORKDIR /restexpress
+COPY --from=maven /restexpress/target/world-1.0-SNAPSHOT.jar app.jar
+CMD ["java", "-jar", "app.jar"]

+ 39 - 46
frameworks/Java/restexpress/src/main/java/hello/Main.java

@@ -1,57 +1,50 @@
 package hello;
 
+import org.restexpress.RestExpress;
+import org.restexpress.common.exception.ConfigurationException;
+import org.restexpress.util.Environment;
+
 import hello.config.Configuration;
 import hello.controller.JsonController.HelloWorld;
-
-import java.io.FileNotFoundException;
-import java.io.IOException;
-
-import java.time.ZoneOffset;
-import java.time.ZonedDateTime;
-import java.time.format.DateTimeFormatter;
-import org.jboss.netty.handler.codec.http.HttpMethod;
-
-import com.strategicgains.restexpress.RestExpress;
-import com.strategicgains.restexpress.util.Environment;
+import io.netty.handler.codec.http.HttpMethod;
+import io.netty.util.ResourceLeakDetector;
+import io.netty.util.ResourceLeakDetector.Level;
 
 public class Main {
-	public static void main(String[] args) throws Exception {
-		Configuration config = loadEnvironment(args);
-		RestExpress server = new RestExpress().setName("RestExpress Benchmark")
-				.setExecutorThreadCount(config.getExecutorThreadPoolSize())
-				.alias("HelloWorld", HelloWorld.class);
-
-		server.uri("/restexpress/json", config.getJsonController()).action("helloWorld",
-				HttpMethod.GET);
-
-		server.uri("/restexpress/plaintext", config.getPlaintextController())
-				.action("helloWorld", HttpMethod.GET).noSerialization();
-
-		server.uri("/restexpress/mysql/db", config.getDbMysqlController()).method(HttpMethod.GET);
-
-		server.uri("/restexpress/mysql/query", config.getQueriesMysqlController()).method(
-				HttpMethod.GET);
-
-		server.uri("/restexpress/mongo/db", config.getDbMongodbController()).method(HttpMethod.GET);
-		
-		server.uri("/restexpress/mongo/query", config.getQueriesMongodbController()).method(HttpMethod.GET);
-
-		server.addPostprocessor((request, response) -> {
-			response.addHeader("Server", "RestExpress");
-			response.addHeader("Date",
-					DateTimeFormatter.RFC_1123_DATE_TIME.format(ZonedDateTime.now(ZoneOffset.UTC)));
-		});
-
-		server.bind(config.getPort());
-		server.awaitShutdown();
+	static {
+		// Netty optimization.
+		ResourceLeakDetector.setLevel(Level.DISABLED);
 	}
 
-	private static Configuration loadEnvironment(String[] args) throws FileNotFoundException,
-			IOException {
-		if (args.length > 0) {
-			return Environment.from(args[0], Configuration.class);
+	public static void main(String[] args) throws Throwable {
+		Configuration config = Environment.load(args, Configuration.class);
+		RestExpress server = new RestExpress().setName("RestExpress")
+				.setExecutorThreadCount(config.getExecutorThreadPoolSize()).setUseTcpNoDelay(true)
+				.setKeepAlive(true).noCompression().setEnforceHttpSpec(true)
+				.alias("HelloWorld", HelloWorld.class)
+				.addPostprocessor(new RequiredResponseHeaders());
+
+		switch (config.getDatabase()) {
+		case MongoDB: {
+			server.uri("/plaintext", config.getPlaintextController()).action("sayHello",
+					HttpMethod.GET).noSerialization();
+			server.uri("/json", config.getJsonController()).action("sayHello", HttpMethod.GET);
+			
+			server.uri("/db", config.getMongodbController()).method(HttpMethod.GET);
+			server.uri("/query", config.getQueriesMongodbController()).method(HttpMethod.GET);
+		}
+			break;
+		case MySQL: {
+			server.uri("/db", config.getMysqlController()).method(HttpMethod.GET);
+			server.uri("/query", config.getQueriesMysqlController()).method(HttpMethod.GET);
+		}
+			break;
+		default:
+			throw new ConfigurationException(
+					"No Database configured in the environment.properties file.");
 		}
 
-		return Environment.fromDefault(Configuration.class);
+		server.bind(config.getPort());
+		server.awaitShutdown();
 	}
-}
+}

+ 23 - 0
frameworks/Java/restexpress/src/main/java/hello/RequiredResponseHeaders.java

@@ -0,0 +1,23 @@
+package hello;
+import static io.netty.handler.codec.http.HttpHeaderNames.DATE;
+import static io.netty.handler.codec.http.HttpHeaderNames.SERVER;
+
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+
+import org.restexpress.Request;
+import org.restexpress.Response;
+import org.restexpress.pipeline.Postprocessor;
+
+public class RequiredResponseHeaders implements Postprocessor {
+	private static final String HEADER_SERVER = SERVER.toString();
+	private static final String SERVER_NAME = "RestExpress";
+	private static final String HEADER_DATE = DATE.toString();
+	
+	@Override
+	public void process(Request request, Response response) {
+		response.addHeader(HEADER_SERVER, SERVER_NAME);
+		response.addHeader(HEADER_DATE, DateTimeFormatter.RFC_1123_DATE_TIME.format(ZonedDateTime.now()));
+	}
+
+}

+ 45 - 37
frameworks/Java/restexpress/src/main/java/hello/config/Configuration.java

@@ -1,20 +1,20 @@
 package hello.config;
 
-import hello.controller.DbMongodbController;
-import hello.controller.DbMysqlController;
+import java.util.Properties;
+
+import org.restexpress.Format;
+import org.restexpress.util.Environment;
+
+import com.strategicgains.repoexpress.mongodb.MongoConfig;
+
 import hello.controller.JsonController;
+import hello.controller.MongodbController;
+import hello.controller.MysqlController;
 import hello.controller.PlaintextController;
 import hello.controller.QueriesMongodbController;
 import hello.controller.QueriesMysqlController;
 import hello.controller.persistence.WorldsMongodbRepository;
 
-import java.util.Properties;
-
-import com.strategicgains.repoexpress.adapter.IdentiferAdapter;
-import com.strategicgains.repoexpress.exception.InvalidObjectIdException;
-import com.strategicgains.restexpress.Format;
-import com.strategicgains.restexpress.util.Environment;
-
 public class Configuration extends Environment {
 	private static final String DEFAULT_EXECUTOR_THREAD_POOL_SIZE = "20";
 
@@ -27,13 +27,14 @@ public class Configuration extends Environment {
 	private String defaultFormat;
 	private String baseUrl;
 	private int executorThreadPoolSize;
+	private Database database = null;
 
+	private PlaintextController plaintextController;
 	private JsonController jsonController;
-	private DbMysqlController dbMysqlController;
+	private MysqlController mysqlController;
 	private QueriesMysqlController queriesMysqlController;
-	private DbMongodbController dbMongodbController;
+	private MongodbController mongodbController;
 	private QueriesMongodbController queriesMongodbController;
-	private PlaintextController plaintextController;
 
 	@Override
 	protected void fillValues(Properties p) {
@@ -42,27 +43,30 @@ public class Configuration extends Environment {
 		this.baseUrl = p.getProperty(BASE_URL_PROPERTY, "http://localhost:" + String.valueOf(port));
 		this.executorThreadPoolSize = Integer.parseInt(p.getProperty(EXECUTOR_THREAD_POOL_SIZE,
 				DEFAULT_EXECUTOR_THREAD_POOL_SIZE));
-		MongoConfig mongoSettings = new MongoConfig(p);
-		MysqlConfig mysqlSettings = new MysqlConfig(p);
-		initialize(mysqlSettings, mongoSettings);
+		if (p.containsKey("mongodb.uri")) {
+			MongoConfig mongoSettings = new MongoConfig(p);
+			initialize(mongoSettings);
+			database = Database.MongoDB;
+		} else if (p.containsKey("mysql.uri")) {
+			MysqlConfig mysqlSettings = new MysqlConfig(p);
+			initialize(mysqlSettings);
+			database = Database.MySQL;
+		}
 	}
 
-	private void initialize(MysqlConfig mysqlSettings, MongoConfig mongo) {
-		jsonController = new JsonController();
-		plaintextController = new PlaintextController();
-		dbMysqlController = new DbMysqlController(mysqlSettings.getDataSource());
-		queriesMysqlController = new QueriesMysqlController(mysqlSettings.getDataSource());
+	private void initialize(MongoConfig mongo) {
 		WorldsMongodbRepository worldMongodbRepository = new WorldsMongodbRepository(
 				mongo.getClient(), mongo.getDbName());
-		worldMongodbRepository.setIdentifierAdapter(new IdentiferAdapter<Long>() {
-			@Override
-			public Long convert(String id) throws InvalidObjectIdException {
-				return Long.valueOf(id);
-			}
-		});
-		dbMongodbController = new DbMongodbController(worldMongodbRepository);
+		plaintextController = new PlaintextController();
+		jsonController = new JsonController();
+		mongodbController = new MongodbController(worldMongodbRepository);
 		queriesMongodbController = new QueriesMongodbController(worldMongodbRepository);
 	}
+	
+	private void initialize(MysqlConfig mysqlSettings) {
+		mysqlController = new MysqlController(mysqlSettings.getDataSource());
+		queriesMysqlController = new QueriesMysqlController(mysqlSettings.getDataSource());
+	}
 
 	public String getDefaultFormat() {
 		return defaultFormat;
@@ -80,27 +84,31 @@ public class Configuration extends Environment {
 		return executorThreadPoolSize;
 	}
 
+	public Database getDatabase() {
+		return database;
+	}
+
+	public PlaintextController getPlaintextController() {
+		return plaintextController;
+	}
+	
 	public JsonController getJsonController() {
 		return jsonController;
 	}
 
-	public DbMysqlController getDbMysqlController() {
-		return dbMysqlController;
+	public MysqlController getMysqlController() {
+		return mysqlController;
 	}
 
 	public QueriesMysqlController getQueriesMysqlController() {
 		return queriesMysqlController;
 	}
 
-	public DbMongodbController getDbMongodbController() {
-		return dbMongodbController;
+	public MongodbController getMongodbController() {
+		return mongodbController;
 	}
-	
+
 	public QueriesMongodbController getQueriesMongodbController() {
 		return queriesMongodbController;
 	}
-
-	public PlaintextController getPlaintextController() {
-		return plaintextController;
-	}
-}
+}

+ 5 - 0
frameworks/Java/restexpress/src/main/java/hello/config/Database.java

@@ -0,0 +1,5 @@
+package hello.config;
+
+public enum Database {
+	MongoDB, MySQL;
+}

+ 12 - 23
frameworks/Java/restexpress/src/main/java/hello/config/MongoConfig.java

@@ -1,47 +1,36 @@
 package hello.config;
 
-import java.net.UnknownHostException;
 import java.util.Properties;
 
+import org.restexpress.common.exception.ConfigurationException;
+
 import com.mongodb.MongoClient;
 import com.mongodb.MongoClientURI;
-import com.strategicgains.restexpress.exception.ConfigurationException;
 
-public class MongoConfig
-{
+public class MongoConfig {
 	private static final String URI_PROPERTY = "mongodb.uri";
 
 	private String dbName;
 	private MongoClient client;
 
-    public MongoConfig(Properties p)
-    {
+	public MongoConfig(Properties p) {
 		String uri = p.getProperty(URI_PROPERTY);
 
-		if (uri == null)
-		{
-			throw new ConfigurationException("Please define a MongoDB URI for property: " + URI_PROPERTY);
+		if (uri == null) {
+			throw new ConfigurationException("Please define a MongoDB URI for property: "
+					+ URI_PROPERTY);
 		}
 
 		MongoClientURI mongoUri = new MongoClientURI(uri);
 		dbName = mongoUri.getDatabase();
-		try
-        {
-	        client = new MongoClient(mongoUri);
-        }
-        catch (UnknownHostException e)
-        {
-        	throw new ConfigurationException(e);
-        }
-    }
-
-	public String getDbName()
-	{
+		client = new MongoClient(mongoUri);
+	}
+
+	public String getDbName() {
 		return dbName;
 	}
 
-	public MongoClient getClient()
-	{
+	public MongoClient getClient() {
 		return client;
 	}
 }

+ 51 - 23
frameworks/Java/restexpress/src/main/java/hello/config/MysqlConfig.java

@@ -4,41 +4,69 @@ import java.util.Properties;
 
 import javax.sql.DataSource;
 
+import org.apache.commons.dbcp.datasources.SharedPoolDataSource;
+import org.restexpress.common.exception.ConfigurationException;
+
 import com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource;
-import com.strategicgains.restexpress.exception.ConfigurationException;
 
-public class MysqlConfig
-{
-	private static final String URI_PROPERTY = "mysql.uri";
-	private static final String USE_CONFIGS_PROPERTY = "mysql.useConfigs";
+public class MysqlConfig {
+	private static final String PREFIX = "mysql.";
+	private static final String URI_PROPERTY = PREFIX + "uri";
+	private static final String USE_CONFIGS_PROPERTY = PREFIX + "useConfigs";
+	private static final String USER_NAME = PREFIX + "user";
+	private static final String PASSWORD = PREFIX + "password";
+	private static final String MAX_POOL_SIZE = PREFIX + "maxPoolSize";
+	private static final String MIN_POOL_SIZE = PREFIX + "minPoolSize";
 
 	private DataSource dataSource;
 
-	public MysqlConfig(Properties p)
-    {
+	public MysqlConfig(Properties p) {
 		String uri = p.getProperty(URI_PROPERTY);
 		String useConfigs = p.getProperty(USE_CONFIGS_PROPERTY);
+		String dbUser = p.getProperty(USER_NAME);
+		String dbPassword = p.getProperty(PASSWORD);
+		int maxPoolSize = Integer.valueOf(p.getProperty(MAX_POOL_SIZE, "100"));
+		int minPoolSize = Integer.valueOf(p.getProperty(MIN_POOL_SIZE, "3"));
 
-		if (uri == null)
-		{
-			throw new ConfigurationException("Please define a MySQL URI for property: " + URI_PROPERTY);
+		if (uri == null) {
+			throw new ConfigurationException("Please define a MySQL URI for property: "
+					+ URI_PROPERTY);
 		}
-		
+
+		MysqlConnectionPoolDataSource ds = configureMysqlConnections(uri, dbUser, dbPassword,
+				useConfigs);
+		this.dataSource = configurePoolingDataSource(ds, maxPoolSize, minPoolSize);
+	}
+
+	private MysqlConnectionPoolDataSource configureMysqlConnections(String uri, String dbUser,
+			String dbPassword, String useConfigs) {
 		MysqlConnectionPoolDataSource ds = new MysqlConnectionPoolDataSource();
 		ds.setUrl(uri);
-		
-		if (useConfigs != null)
-		{
+
+		if (dbUser != null) {
+			ds.setUser(dbUser);
+		}
+
+		if (dbPassword != null) {
+			ds.setPassword(dbPassword);
+		}
+
+		if (useConfigs != null) {
 			ds.setUseConfigs(useConfigs);
 		}
-		ds.setUser("benchmarkdbuser");
-		ds.setPassword("benchmarkdbpass");
+		return ds;
+	}
 
-		this.dataSource = ds;
-    }
+	public DataSource getDataSource() {
+		return dataSource;
+	}
 
-	public DataSource getDataSource()
-    {
-	    return dataSource;
-    }
-}
+	private DataSource configurePoolingDataSource(MysqlConnectionPoolDataSource ds,
+			int maxPoolSize, int minPoolSize) {
+		SharedPoolDataSource spds = new SharedPoolDataSource();
+		spds.setConnectionPoolDataSource(ds);
+		spds.setMaxActive(maxPoolSize);
+		spds.setMaxIdle(minPoolSize);
+		return spds;
+	}
+}

+ 7 - 9
frameworks/Java/restexpress/src/main/java/hello/controller/JsonController.java

@@ -1,21 +1,19 @@
 package hello.controller;
 
-import com.strategicgains.restexpress.Request;
-import com.strategicgains.restexpress.Response;
+import org.restexpress.Request;
+import org.restexpress.Response;
 
-public class JsonController
-{
-	public HelloWorld helloWorld(Request request, Response response)
-	{
+public class JsonController {
+
+	public HelloWorld sayHello(Request request, Response response) {
 		return new HelloWorld();
 	}
 
 	/**
 	 * Inner class just to illustrate JSON serialization.
 	 */
-	public static class HelloWorld
-	{
+	public static class HelloWorld {
 		@SuppressWarnings("unused")
-        private String message = "Hello, World!";
+		private String message = "Hello, World!";
 	}
 }

+ 9 - 8
frameworks/Java/restexpress/src/main/java/hello/controller/DbMongodbController.java → frameworks/Java/restexpress/src/main/java/hello/controller/MongodbController.java

@@ -4,24 +4,25 @@ import hello.controller.persistence.WorldsMongodbRepository;
 
 import java.util.concurrent.ThreadLocalRandom;
 
-import com.strategicgains.restexpress.Request;
-import com.strategicgains.restexpress.Response;
+import org.restexpress.Request;
+import org.restexpress.Response;
 
-public class DbMongodbController {
+public class MongodbController {
 	// Database details.
 	private static final int DB_ROWS = 10000;
 
 	private WorldsMongodbRepository worldRepo;
 
-	public DbMongodbController(WorldsMongodbRepository worldsRepository) {
+	public MongodbController(WorldsMongodbRepository worldsRepository) {
 		super();
 		this.worldRepo = worldsRepository;
 	}
 
 	public Object read(Request request, Response response) {
-		// Fetch some rows from the database.
-		final int random = 1 + ThreadLocalRandom.current().nextInt(DB_ROWS);
+		return worldRepo.find(generateIdentifier());
+	}
 
-		return worldRepo.find(random);
+	private int generateIdentifier() {
+		return ThreadLocalRandom.current().nextInt(DB_ROWS) + 1;
 	}
-}
+}

+ 9 - 9
frameworks/Java/restexpress/src/main/java/hello/controller/DbMysqlController.java → frameworks/Java/restexpress/src/main/java/hello/controller/MysqlController.java

@@ -10,38 +10,38 @@ import java.util.concurrent.ThreadLocalRandom;
 
 import javax.sql.DataSource;
 
-import com.strategicgains.restexpress.Request;
-import com.strategicgains.restexpress.Response;
+import org.restexpress.Request;
+import org.restexpress.Response;
 
-public class DbMysqlController {
+public class MysqlController {
 	// Database details.
 	private static final String DB_QUERY = "SELECT * FROM World WHERE id = ?";
 	private static final int DB_ROWS = 10000;
 
 	private DataSource mysqlDataSource;
 
-	public DbMysqlController(DataSource dataSource) {
+	public MysqlController(DataSource dataSource) {
 		super();
 		this.mysqlDataSource = dataSource;
 	}
 
 	public Object read(Request request, Response response) throws SQLException {
-		final int random = 1 + ThreadLocalRandom.current().nextInt(DB_ROWS);
-
 		World world = null;
 
 		// Fetch some rows from the database.
 		try (Connection conn = mysqlDataSource.getConnection()) {
 			try (PreparedStatement statement = conn.prepareStatement(DB_QUERY,
 					ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)) {
-				statement.setInt(1, random);
+				final Long id = (long) (ThreadLocalRandom.current().nextInt(DB_ROWS) + 1);
+				statement.setLong(1, id);
 				try (ResultSet results = statement.executeQuery()) {
-					results.next(); // Here the expectation is ONLY one
+					results.next(); // Here the expectation is ONLY only one
 									// result row
 					world = new World(results.getLong("id"), results.getInt("randomNumber"));
 				}
 			}
 		}
+		
 		return world;
 	}
-}
+}

+ 3 - 3
frameworks/Java/restexpress/src/main/java/hello/controller/PlaintextController.java

@@ -1,13 +1,13 @@
 package hello.controller;
 
-import com.strategicgains.restexpress.Request;
-import com.strategicgains.restexpress.Response;
+import org.restexpress.Request;
+import org.restexpress.Response;
 
 public class PlaintextController
 {
 	private static final String MESSAGE = "Hello, World!";
 
-	public String helloWorld(Request request, Response response)
+	public String sayHello(Request request, Response response)
 	{
 		response.setContentType("text/plain");
 		return MESSAGE;

+ 14 - 17
frameworks/Java/restexpress/src/main/java/hello/controller/QueriesMongodbController.java

@@ -5,8 +5,8 @@ import hello.domain.World;
 
 import java.util.concurrent.ThreadLocalRandom;
 
-import com.strategicgains.restexpress.Request;
-import com.strategicgains.restexpress.Response;
+import org.restexpress.Request;
+import org.restexpress.Response;
 
 public class QueriesMongodbController {
 	// Database details.
@@ -21,21 +21,7 @@ public class QueriesMongodbController {
 
 	public Object read(Request request, Response response) {
 		// Get the count of queries to run.
-		int count = 1;
-		try {
-			count = Integer.parseInt(request.getHeader("queries"));
-
-			// Bounds check.
-			if (count > 500) {
-				count = 500;
-			}
-			if (count < 1) {
-				count = 1;
-			}
-		} catch (NumberFormatException nfexc) {
-			// do nothing
-		}
-
+		int count = determineQueryCount(request);
 		// Fetch some rows from the database.
 		final World[] worlds = new World[count];
 		final int random = 1 + ThreadLocalRandom.current().nextInt(DB_ROWS);
@@ -45,4 +31,15 @@ public class QueriesMongodbController {
 
 		return worlds;
 	}
+
+	private int determineQueryCount(Request request) {
+		String value = request.getHeader("queries");
+
+		try {
+			int parsedValue = Integer.parseInt(value);
+			return Math.min(500, Math.max(1, parsedValue));
+		} catch (NumberFormatException e) {
+			return 1;
+		}
+	}
 }

+ 19 - 24
frameworks/Java/restexpress/src/main/java/hello/controller/QueriesMysqlController.java

@@ -10,40 +10,24 @@ import java.util.concurrent.ThreadLocalRandom;
 
 import javax.sql.DataSource;
 
-import com.strategicgains.restexpress.Request;
-import com.strategicgains.restexpress.Response;
+import org.restexpress.Request;
+import org.restexpress.Response;
 
-public class QueriesMysqlController
-{
+public class QueriesMysqlController {
 	// Database details.
 	private static final String DB_QUERY = "SELECT * FROM World WHERE id = ?";
 	private static final int DB_ROWS = 10000;
 
 	private DataSource mysqlDataSource;
 
-	public QueriesMysqlController(DataSource dataSource)
-	{
+	public QueriesMysqlController(DataSource dataSource) {
 		super();
 		this.mysqlDataSource = dataSource;
 	}
 
-	public Object read(Request request, Response response)
-	throws SQLException
-	{
-		int count = 1;
-		try {
-			count = Integer.parseInt(request.getHeader("queries"));
-			// Bounds checks
-			if (count > 500) {
-				count = 500;
-			} else if (count < 1) {
-				count = 1;
-			}
-		} catch (NumberFormatException nfexc) {
-			//do nothing
-		}		
+	public Object read(Request request, Response response) throws SQLException {
+		final int count = getQueryCount(request);
 		final World[] worlds = new World[count];
-		final int random = 1 + ThreadLocalRandom.current().nextInt(DB_ROWS);
 
 		// Fetch some rows from the database.
 		try (Connection conn = mysqlDataSource.getConnection()) {
@@ -51,12 +35,12 @@ public class QueriesMysqlController
 					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;
+					final int id = 1 + ThreadLocalRandom.current().nextInt(DB_ROWS);
 					statement.setInt(1, id);
 
 					try (ResultSet results = statement.executeQuery()) {
 						results.next();
-						worlds[i] = new World(new Long(id), results.getInt("randomNumber"));
+						worlds[i] = new World(results.getLong("id"), results.getInt("randomNumber"));
 					}
 				}
 			}
@@ -64,4 +48,15 @@ public class QueriesMysqlController
 
 		return worlds;
 	}
+
+	private int getQueryCount(Request request) {
+		String value = request.getHeader("queries");
+
+		try {
+			int parsedValue = Integer.parseInt(value);
+			return Math.min(500, Math.max(1, parsedValue));
+		} catch (NumberFormatException e) {
+			return 1;
+		}
+	}
 }

+ 392 - 0
frameworks/Java/restexpress/src/main/java/hello/controller/persistence/MongodbRepository.java

@@ -0,0 +1,392 @@
+/*
+Copyright 2010-2012, Strategic Gains, Inc.
+
+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 hello.controller.persistence;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.mongodb.morphia.Datastore;
+import org.mongodb.morphia.Morphia;
+import org.mongodb.morphia.query.Query;
+import org.restexpress.common.query.FilterCallback;
+import org.restexpress.common.query.FilterComponent;
+import org.restexpress.common.query.OrderCallback;
+import org.restexpress.common.query.OrderComponent;
+import org.restexpress.common.query.QueryFilter;
+import org.restexpress.common.query.QueryOrder;
+import org.restexpress.common.query.QueryRange;
+
+import com.mongodb.Mongo;
+import com.mongodb.MongoClient;
+import com.strategicgains.repoexpress.AbstractObservableRepository;
+import com.strategicgains.repoexpress.Queryable;
+import com.strategicgains.repoexpress.domain.Identifiable;
+import com.strategicgains.repoexpress.domain.Identifier;
+import com.strategicgains.repoexpress.exception.DuplicateItemException;
+import com.strategicgains.repoexpress.exception.InvalidObjectIdException;
+import com.strategicgains.repoexpress.exception.ItemNotFoundException;
+
+/**
+* Uses MongoDB as its back-end store to persist Identifiable implementations.
+* This repository can handle "single-table inheritance" by passing all the
+* supported types into the constructor, with the inheritance root listed first.
+* 
+* @author toddf
+* @since Aug 24, 2010
+*/
+public class MongodbRepository<T extends Identifiable>
+extends AbstractObservableRepository<T>
+implements Queryable<T>
+{
+private MongoClient mongo;
+private Morphia morphia;
+private Datastore datastore;
+private Class<T> inheritanceRoot;
+
+/**
+ * 
+ * @param mongo a pre-configured Mongo instance.
+ * @param dbName the name of the database (in MongoDB).
+ * @param entityClasses Class(es) managed by this repository. Inheritance root first.
+ */
+public MongodbRepository(MongoClient mongo, String dbName, boolean skipEnsureSteps, Class<? extends T>... entityClasses)
+{
+	super();
+	this.mongo = mongo;
+	initialize(dbName, skipEnsureSteps, entityClasses);
+}
+
+@SuppressWarnings("unchecked")
+private void initialize(String name, boolean skipEnsureSteps, Class<? extends T>... entityClasses)
+{
+	morphia = new Morphia();
+	inheritanceRoot = (Class<T>) entityClasses[0];
+
+	for (Class<?> entityClass : entityClasses)
+	{
+		morphia.map(entityClass);
+	}
+
+	datastore = morphia.createDatastore(mongo, name);
+	if (!skipEnsureSteps) {
+		datastore.ensureIndexes();
+		datastore.ensureCaps();
+	}
+}
+
+@Override
+public T doCreate(T item)
+{
+	if (exists(item.getId()))
+	{
+		throw new DuplicateItemException(item.getClass().getSimpleName()
+		    + " ID already exists: " + item.getId());
+	}
+
+	datastore.save(item);
+	return item;
+}
+
+@Override
+public T doRead(Identifier id)
+{
+	T item = datastore.get(inheritanceRoot, id.primaryKey());
+
+	if (item == null)
+	{
+		throw new ItemNotFoundException("ID not found: " + id);
+	}
+
+	return item;
+}
+
+@Override
+public T doUpdate(T item)
+{
+	if (!exists(item.getId()))
+	{
+		throw new ItemNotFoundException(item.getClass().getSimpleName()
+		    + " ID not found: " + item.getId());
+	}
+
+	datastore.save(item);
+	return item;
+}
+
+@Override
+public void doDelete(T object)
+{
+	try
+	{
+		datastore.delete(object);
+	}
+	catch (InvalidObjectIdException e)
+	{
+		throw new ItemNotFoundException("ID not found: " + object.getId());
+	}
+}
+
+/**
+ * A general-purpose 'finder' method, useful for implementing alternate-key queries. Since
+ * it does not support ordering and range sub-sets, it's best for creating queries that
+ * return a list size of 1.
+ * <p/>
+ * Essentially, just calls readAll() with null range and order.  So if you need ordering,
+ * call readAll(filter, null, order).
+ * 
+ * @param filter query criteria.
+ * @return
+ */
+public List<T> find(QueryFilter filter)
+{
+	return readAll(filter, null, null);
+}
+
+/**
+ * Implements a 'default' readAll' method that queries for all instances of the inheritance
+ * root class matching the given criteria.
+ * 
+ * This method does not invoke an observer method, so is not observable by default.  Override,
+ * calling super() to get that functionality, or call notifyBeforeXXX() and/or notifyAfterXXX()
+ * methods, if desired.
+ * 
+ * @param filter
+ * @param range
+ * @param order
+ * @return a list of results. Never null.
+ */
+@Override
+public List<T> readAll(QueryFilter filter, QueryRange range, QueryOrder order)
+{
+	return query(inheritanceRoot, filter, range, order);
+}
+
+/**
+ * Read each of the instances corresponding to the given Collection of IDs, returning the 
+ * results as a list.  If an ID in the provided Collection does not exist, it is simply
+ * not included in the returned results.
+ * 
+ * @param ids a Collection of IDs to read.
+ */
+@Override
+public List<T> readList(Collection<Identifier> ids)
+{
+	return getDataStore().find(inheritanceRoot).field("_id").in(new PrimaryIdIterable(ids)).asList();
+}
+
+/**
+ * Count the instances of the inheritance root (class) that match the given filter criteria.
+ * 
+ * @param filter
+ */
+@Override
+public long count(QueryFilter filter)
+{
+	return count(inheritanceRoot, filter);
+}
+
+/**
+ * Count the instances of the given type matching the given filter criteria.
+ * 
+ * @param type
+ * @param filter
+ */
+public long count(Class<T> type, QueryFilter filter)
+{
+	return getBaseFilterQuery(type, filter).countAll();
+}
+
+/**
+ * Returns true if the given id exists in the repository.
+ * 
+ * @param id the identifier of the object.
+ */
+@Override
+public boolean exists(Identifier id)
+{
+	if (id == null) return false;
+
+	return (datastore.getCount(datastore.find(inheritanceRoot, "_id", id.primaryKey())) > 0);
+
+	// is the above line more efficient, or the following one?
+//	return (datastore.find(inheritanceRoot, "_id", adaptId(id)).countAll() > 0);
+}
+
+
+// SECTION: UTILITY
+
+/**
+ * Get the underlying Morphia Datastore object with which to construct queries against.
+ * 
+ * @return the underlying Morphia Datastore.
+ */
+protected Datastore getDataStore()
+{
+	return datastore;
+}
+
+/**
+ * Return the underlying Mongo instance.
+ * 
+ * @return the underlying Mongo instance.
+ */
+protected Mongo getMongo()
+{
+	return mongo;
+}
+
+/**
+ * Execute a query against the repository, using QueryFilter, QueryRange and QueryOrder
+ * as criteria against the type.  Returns the results as a List.
+ * 
+ * @param type
+ * @param range
+ * @param filter
+ * @param order
+ */
+protected List<T> query(Class<T> type, QueryFilter filter, QueryRange range, QueryOrder order)
+{
+	return getBaseQuery(type, filter, range, order).asList();
+}
+
+/**
+ * Create and configure a basic query utilizing provided QueryFilter, QueryRange and QueryOrder
+ * criteria, returning the query.
+ * 
+ * @param type
+ * @param range
+ * @param filter
+ * @param order
+ */
+protected Query<T> getBaseQuery(Class<T> type, QueryFilter filter, QueryRange range, QueryOrder order)
+{
+	Query<T> q = getBaseFilterQuery(type, filter);
+	configureQueryRange(q, range);
+	configureQueryOrder(q, order);
+	return q;
+}
+
+/**
+ * Create and configure a basic query utilizing just QueryFilter as criteria.
+ * 
+ * @param type
+ * @param filter
+ * @return a Morphia Query instance configured for the QueryFilter criteria.
+ */
+private Query<T> getBaseFilterQuery(Class<T> type, QueryFilter filter)
+{
+	Query<T> q = getDataStore().find(type);
+	configureQueryFilter(q, filter);
+	return q;
+}
+
+/**
+ * @param q
+ * @param range
+ */
+private void configureQueryRange(Query<T> q, QueryRange range)
+{
+	if (range == null) return;
+
+	if (range.isInitialized())
+	{
+		q.offset((int) range.getStart());
+		q.limit(range.getLimit());
+	}
+}
+
+private void configureQueryFilter(final Query<T> q, QueryFilter filter)
+{
+	if (filter == null) return;
+
+	filter.iterate(new FilterCallback()
+	{
+		@Override
+		public void filterOn(FilterComponent c)
+		{
+			switch(c.getOperator())
+			{
+				case CONTAINS:		// String-related
+					q.field(c.getField()).contains((c.getValue().toString()));
+					break;
+				case STARTS_WITH:	// String-related
+					q.field(c.getField()).startsWith(c.getValue().toString());
+					break;
+				case GREATER_THAN:
+					q.field(c.getField()).greaterThan(c.getValue());
+					break;
+				case GREATER_THAN_OR_EQUAL_TO:
+					q.field(c.getField()).greaterThanOrEq(c.getValue());
+					break;
+				case LESS_THAN:
+					q.field(c.getField()).lessThan(c.getValue());
+					break;
+				case LESS_THAN_OR_EQUAL_TO:
+					q.field(c.getField()).lessThanOrEq(c.getValue());
+					break;
+				case NOT_EQUALS:
+					q.field(c.getField()).notEqual(c.getValue());
+					break;
+				case IN:
+					q.field(c.getField()).in((Iterable<?>) c.getValue());
+					break;
+				case EQUALS:
+				default:
+					q.field(c.getField()).equal(c.getValue());
+					break;
+			}
+		}
+	});
+}
+
+/**
+ * @param q
+ * @param order
+ */
+private void configureQueryOrder(Query<T> q, QueryOrder order)
+{
+	if (order == null) return;
+
+	if (order.isSorted())
+	{
+		final StringBuilder sb = new StringBuilder();
+		
+		order.iterate(new OrderCallback()
+		{
+			boolean isFirst = true;
+
+			@Override
+			public void orderBy(OrderComponent component)
+			{
+				if (!isFirst)
+				{
+					sb.append(',');
+				}
+				
+				if (component.isDescending())
+				{
+					sb.append('-');
+				}
+
+				sb.append(component.getFieldName());
+				isFirst = false;
+			}
+		});
+		
+		q.order(sb.toString());
+	}
+}
+}

+ 23 - 14
frameworks/Java/restexpress/src/main/java/hello/controller/persistence/WorldsMongodbRepository.java

@@ -1,21 +1,30 @@
 package hello.controller.persistence;
 
-import hello.domain.World;
+import java.util.List;
+
+import com.mongodb.MongoClient;
 
-import com.mongodb.Mongo;
-import com.strategicgains.repoexpress.mongodb.MongodbRepository;
+import hello.domain.World;
 
-public class WorldsMongodbRepository
-extends MongodbRepository<World, Long>
-{
+public class WorldsMongodbRepository extends MongodbRepository<World> {
 	@SuppressWarnings("unchecked")
-    public WorldsMongodbRepository(Mongo mongo, String dbName)
-    {
-	    super(mongo, dbName, World.class);
-    }
+	public WorldsMongodbRepository(MongoClient mongo, String dbName) {
+		//TODO from zloster
+		// This is a nice example for one kind of problem with the
+		// object-oriented approach. You have a piece of functionality which is
+		// not separated in an object/function. But you have to modify it. The
+		// solution is to rewrite and unwind the whole thing. But this requires time, effort and devotion.
+		// So copy-pasty approach was chosen.
+		super(mongo, dbName, true, World.class);
+	}
+
+	public World find(int id) {
+		return getDataStore().find(World.class, "id", (long) id).retrievedFields(false, "_id")
+				.get();
+	}
 
-	public World find(int id)
-	{
-		return getDataStore().find(World.class, "id", (long) id).retrievedFields(false, "_id").get();
+	public World findAll(List<Integer> ids) {
+		return getDataStore().find(World.class).field("id").in(ids).retrievedFields(false, "_id")
+				.get();
 	}
-}
+}

+ 16 - 20
frameworks/Java/restexpress/src/main/java/hello/domain/World.java

@@ -1,44 +1,40 @@
 package hello.domain;
 
 import org.bson.types.ObjectId;
+import org.mongodb.morphia.annotations.Entity;
+import org.mongodb.morphia.annotations.Id;
+import org.mongodb.morphia.annotations.Indexed;
 
-import com.github.jmkgreen.morphia.annotations.Entity;
-import com.github.jmkgreen.morphia.annotations.Id;
 import com.strategicgains.repoexpress.domain.Identifiable;
+import com.strategicgains.repoexpress.domain.Identifier;
 
-@Entity(value="world", noClassnameStored=true)
-public class World
-implements Identifiable
-{
+@Entity(value = "world", noClassnameStored = true)
+public class World implements Identifiable {
 	@Id
 	private ObjectId oid;
 
+	@Indexed(unique = true)
 	private Long id;
 	private int randomNumber;
 
-	public World()
-	{
+	public World() {
 		super();
 	}
 
-	public World(Long id, int randomNumber)
-	{
+	public World(Long id, int randomNumber) {
 		this.id = id;
 		this.randomNumber = randomNumber;
 	}
 
-	public String getId()
-	{
-		return (id == null ? null : id.toString());
+	public Identifier getId() {
+		return (id == null ? null : new Identifier(id));
 	}
-	
-	public void setId(String id)
-	{
-		this.id = (id == null ? null : Long.parseLong(id));
+
+	public void setId(Identifier id) {
+		this.id = (id == null ? null : (Long) id.primaryKey());
 	}
 
-	public int getRandomNumber()
-	{
+	public int getRandomNumber() {
 		return this.randomNumber;
 	}
-}
+}

+ 6 - 0
frameworks/Java/restexpress/src/main/resources/config/dev/mongodb-environment.properties

@@ -0,0 +1,6 @@
+# The size of the executor thread pool (that can handle blocking back-end processing).
+executor.threadPool.size = 300
+
+# A MongoDB URI/Connection string
+# see: http://docs.mongodb.org/manual/reference/connection-string/
+mongodb.uri = mongodb://tfb-database:27017/hello_world?maxPoolSize=300

+ 4 - 4
frameworks/Java/restexpress/config/dev/environment.properties → frameworks/Java/restexpress/src/main/resources/config/dev/mysql-environment.properties

@@ -1,10 +1,6 @@
 # The size of the executor thread pool (that can handle blocking back-end processing).
 executor.threadPool.size = 300
 
-# A MongoDB URI/Connection string
-# see: http://docs.mongodb.org/manual/reference/connection-string/
-mongodb.uri = mongodb://tfb-database:27017/hello_world?maxPoolSize=300
-
 # A MySQL URI/Connection string
 mysql.uri = jdbc:mysql://tfb-database:3306/hello_world?useSSL=false
 
@@ -12,3 +8,7 @@ mysql.uri = jdbc:mysql://tfb-database:3306/hello_world?useSSL=false
 # http://dev.mysql.com/doc/refman/5.6/en/connector-j-reference-configuration-properties.html
 # Empty is a valid selection.
 mysql.useConfigs = maxPerformance
+mysql.user = benchmarkdbuser
+mysql.password = benchmarkdbpass
+mysql.maxPoolSize = 300
+mysql.minPoolSize = 10

+ 0 - 34
frameworks/Java/restexpress/zip-with-dependencies.xml

@@ -1,34 +0,0 @@
-<assembly
-	xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
-	<id>zip-with-dependencies</id>
-	<formats>
-		<format>zip</format>
-	</formats>
-	<fileSets>
-		<fileSet>
-			<directory>${project.basedir}</directory>
-			<outputDirectory>/</outputDirectory>
-			<includes>
-				<include>README*</include>
-				<include>LICENSE*</include>
-				<include>NOTICE*</include>
-				<include>config/**/*</include>
-			</includes>
-		</fileSet>
-		<fileSet>
-			<directory>${project.build.directory}</directory>
-			<outputDirectory>/</outputDirectory>
-			<includes>
-				<include>*.jar</include>
-			</includes>
-		</fileSet>
-	</fileSets>
-	<dependencySets>
-		<dependencySet>
-			<outputDirectory>lib</outputDirectory>
-			<useProjectArtifact>false</useProjectArtifact>
-		</dependencySet>
-	</dependencySets>
-</assembly>