Browse Source

Java/dropwizard add jdbi implementation (#2882)

* Java/dropwizard Add JDBI implementation

* Compiler settings
Radoslav Petrov 8 years ago
parent
commit
d71fab29d8
21 changed files with 601 additions and 217 deletions
  1. 66 5
      frameworks/Java/dropwizard/README.md
  2. 46 7
      frameworks/Java/dropwizard/benchmark_config.json
  3. 55 0
      frameworks/Java/dropwizard/hello-world-jdbi-postgres.yml
  4. 0 2
      frameworks/Java/dropwizard/hello-world-mongo.yml
  5. 9 2
      frameworks/Java/dropwizard/hello-world-mysql.yml
  6. 9 2
      frameworks/Java/dropwizard/hello-world-postgres.yml
  7. 157 132
      frameworks/Java/dropwizard/pom.xml
  8. 7 0
      frameworks/Java/dropwizard/setup_jdbi_postgres.sh
  9. 38 0
      frameworks/Java/dropwizard/src/main/java/com/example/helloworld/HelloJDBIService.java
  10. 1 1
      frameworks/Java/dropwizard/src/main/java/com/example/helloworld/HelloWorldService.java
  11. 5 10
      frameworks/Java/dropwizard/src/main/java/com/example/helloworld/db/hibernate/WorldHibernateImpl.java
  12. 17 0
      frameworks/Java/dropwizard/src/main/java/com/example/helloworld/db/jdbi/FortuneJDBIImpl.java
  13. 20 0
      frameworks/Java/dropwizard/src/main/java/com/example/helloworld/db/jdbi/WorldJDBIImpl.java
  14. 63 0
      frameworks/Java/dropwizard/src/main/java/com/example/helloworld/db/jdbi/WorldRepository.java
  15. 16 0
      frameworks/Java/dropwizard/src/main/java/com/example/helloworld/db/mappers/FortuneMapper.java
  16. 16 0
      frameworks/Java/dropwizard/src/main/java/com/example/helloworld/db/mappers/WorldMapper.java
  17. 10 3
      frameworks/Java/dropwizard/src/main/java/com/example/helloworld/db/model/Fortune.java
  18. 5 0
      frameworks/Java/dropwizard/src/main/java/com/example/helloworld/db/model/World.java
  19. 19 19
      frameworks/Java/dropwizard/src/main/java/com/example/helloworld/resources/FortuneResource.java
  20. 8 5
      frameworks/Java/dropwizard/src/main/java/com/example/helloworld/resources/Helper.java
  21. 34 29
      frameworks/Java/dropwizard/src/main/java/com/example/helloworld/resources/WorldResource.java

+ 66 - 5
frameworks/Java/dropwizard/README.md

@@ -1,9 +1,70 @@
 # Dropwizard Benchmarking Test
 # Dropwizard Benchmarking Test
 
 
-This project consists of 3 tests:
+[Dropwizard](http://dropwizard.io/) - ops-friendly, high-performance, RESTful web services.
 
 
-* MySql and Postgres - uses: `HelloWorldService.java` and `HelloWorldConfiguration.java`
-* MongoDB - uses: `HelloMongoService.java` and `HelloMongoConfiguration.java`
+Mustashe tempate is used for the HTML tests.
+Test implementations with MongoDB, MySQL and PostgreSQL for backing datastore.
+Test implementations with Hibernate and JDBI as ORM frameworks, MongoJack for POJO to MongoDB document mapping.
 
 
-All other `resources` and `model` code are shared. The main `*Service.java` is set based on maven profiles.
-Respective `.yml` configuration files are specified in each `setup_*.sh` script.
+**Note**: The [Dropwizard Metrics](http://metrics.dropwizard.io/) are enabled and gathering data during the test runs.
+
+### Test sources
+
+All test implementations share the same API end-points and POJO model classes. The API end-points are called `resources` in Dropwizard. This is the list:
+
+ * [Plaintext](src/main/java/com/example/helloworld/resources/TextResource.java)
+ * [JSON](src/main/java/com/example/helloworld/resources/JsonResource.java)
+ * [DB](src/main/java/com/example/helloworld/resources/WorldResource.java)
+ * [Queries](src/main/java/com/example/helloworld/resources/WorldResource.java)
+ * [Updates](src/main/java/com/example/helloworld/resources/WorldResource.java)
+ * [Fortune](src/main/java/com/example/helloworld/resources/FortuneResource.java)
+
+## Source code organisation
+
+| Test implementation | Dropwizard Service class | Dropwizard Configuration class| Maven profile |
+| --- | --- | --- | --- |
+| MongoDB&MongoJack | HelloMongoService.java | HelloMongoConfiguration.java | `-P mongo` |
+| MySQL&Hibernate | HelloWorldService.java | HelloWorldConfiguration.java | `-P mysql` |
+| PostgreSQL&Hibernate | HelloWorldService.java | HelloWorldConfiguration.java | `-P postgres` |
+| PostgreSQL&JDBI | HelloJDBIService.java | HelloWorldConfiguration.java | `-P postgres,jdbi` |
+
+Each implementation has its own set of `.yml` configuration file and shell script.
+
+### MongoDB
+
+ * [DB, Queries and Updates](src/main/java/com/example/helloworld/db/mongo/WorldMongoImpl.java)
+ * [Fortune](src/main/java/com/example/helloworld/db/mongo/FortuneMongoImpl.java)
+
+### (MySQL or PostgreSQL) and Hibernate
+
+ * [DB, Queries and Updates](src/main/java/com/example/helloworld/db/hibernate/WorldHibernateImpl.java)
+ * [Fortune](src/main/java/com/example/helloworld/db/hibernate/FortuneHibernateImpl.java)
+
+### PostgeSQL and JDBI
+
+ * [DB, Queries and Updates](src/main/java/com/example/helloworld/db/jdbi/WorldRepository.java)
+ * [Fortune](src/main/java/com/example/helloworld/db/jdbi/FortuneJDBIImpl.java)
+
+## Software Versions
+
+The tests were run with:
+
+ * [Oracle Java 1.8](https://www.oracle.com/java/)
+ * [Postgres 9.3](http://www.postgresql.org/)
+ * [MySQL 5.7](http://www.mysql.com/)
+ * [MongoDB 3.2](http://www.mongodb.com/)
+ * [Dropwizard 1.1.1](http://dropwizard.io/)
+ * [MongoJack 2.7.0](http://mongojack.org/)
+
+Please confirm the versions data with the latest install scripts of TFB project.
+
+## Test URLs
+
+All implementations use the same URLs.
+
+ * Plaintext - `http://localhost:9090/plaintext`
+ * JSON - `http://localhost:9090/json`
+ * DB - `http://localhost:9090/db`
+ * Queries - `http://localhost:9090/db?queries=`
+ * Updates - `http://localhost:9090/db/update?queries=?`
+ * Fortune - `http://localhost:9090/fortunes`

+ 46 - 7
frameworks/Java/dropwizard/benchmark_config.json

@@ -4,11 +4,29 @@
     "default": {
     "default": {
       "setup_file": "setup_mysql",
       "setup_file": "setup_mysql",
       "json_url": "/json",
       "json_url": "/json",
+      "plaintext_url": "/plaintext",
+      "port": 9090,
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "none",
+      "framework": "Dropwizard",
+      "language": "Java",
+      "flavor": "None",
+      "orm": "Full",
+      "platform": "JAX-RS",
+      "webserver": "Jetty",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "Dropwizard",
+      "notes": "dropwizard mysql using hibernate",
+      "versus": "servlet"
+    },
+    "mysql": {
+      "setup_file": "setup_mysql",
       "db_url": "/db",
       "db_url": "/db",
-      "query_url": "/db?queries=",
+      "query_url": "/db/query?queries=",
       "fortune_url": "/fortunes",
       "fortune_url": "/fortunes",
       "update_url": "/db/update?queries=",
       "update_url": "/db/update?queries=",
-      "plaintext_url": "/plaintext",
       "port": 9090,
       "port": 9090,
       "approach": "Realistic",
       "approach": "Realistic",
       "classification": "Fullstack",
       "classification": "Fullstack",
@@ -23,12 +41,12 @@
       "database_os": "Linux",
       "database_os": "Linux",
       "display_name": "Dropwizard",
       "display_name": "Dropwizard",
       "notes": "dropwizard mysql using hibernate",
       "notes": "dropwizard mysql using hibernate",
-      "versus": "servlet"
+      "versus": "servlet-raw"
     },
     },
     "mongodb": {
     "mongodb": {
       "setup_file": "setup_mongo",
       "setup_file": "setup_mongo",
       "db_url": "/db",
       "db_url": "/db",
-      "query_url": "/db?queries=",
+      "query_url": "/db/query?queries=",
       "fortune_url": "/fortunes",
       "fortune_url": "/fortunes",
       "update_url": "/db/update?queries=",
       "update_url": "/db/update?queries=",
       "port": 9090,
       "port": 9090,
@@ -50,7 +68,7 @@
     "postgres": {
     "postgres": {
       "setup_file": "setup_postgresql",
       "setup_file": "setup_postgresql",
       "db_url": "/db",
       "db_url": "/db",
-      "query_url": "/db?queries=",
+      "query_url": "/db/query?queries=",
       "fortune_url": "/fortunes",
       "fortune_url": "/fortunes",
       "update_url": "/db/update?queries=",
       "update_url": "/db/update?queries=",
       "port": 9090,
       "port": 9090,
@@ -66,8 +84,29 @@
       "os": "Linux",
       "os": "Linux",
       "database_os": "Linux",
       "database_os": "Linux",
       "display_name": "dropwizard",
       "display_name": "dropwizard",
-      "notes": "dropwizard postgres using hibernate",
-      "versus": "servlet"
+      "notes": "dropwizard PostgreSQL using hibernate",
+      "versus": "servlet-postgres-raw"
+    },
+    "jdbi-postgres": {
+      "setup_file": "setup_jdbi_postgres",
+      "db_url": "/db",
+      "query_url": "/db/query?queries=",
+      "fortune_url": "/fortunes",
+      "update_url": "/db/update?queries=",
+      "port": 9090,
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "Postgres",
+      "framework": "dropwizard",
+      "language": "Java",
+      "orm": "micro",
+      "platform": "JAX-RS",
+      "webserver": "Jetty",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "dropwizard",
+      "notes": "dropwizard PostgreSQL using jdbi",
+      "versus": "servlet-postgres-raw"
     }
     }
   }]
   }]
 }
 }

+ 55 - 0
frameworks/Java/dropwizard/hello-world-jdbi-postgres.yml

@@ -0,0 +1,55 @@
+server:
+  type: simple
+  applicationContextPath: /
+  connector:
+    type: http
+    port: 9090
+    useServerHeader: true
+    # There is no proxy in front of the server
+    useForwardedHeaders: false
+  # Test requirements forgid gzip compression of the replies
+  gzip:
+    enabled: false
+  requestLog:
+    appenders: []
+
+logging:
+  appenders: []
+
+database:
+  # the name of your JDBC driver
+  driverClass: org.postgresql.Driver
+
+  # the username
+  user: benchmarkdbuser
+
+  # the password
+  password: benchmarkdbpass
+
+  # the JDBC URL
+  url: jdbc:postgresql://TFB-database:5432/hello_world
+
+  # any properties specific to your JDBC driver:
+  properties:
+    charSet: UTF-8
+
+  # the maximum amount of time to wait on an empty pool before throwing an exception
+  maxWaitForConnection: 1s
+
+  # the initial number of connections
+  initialSize: 8
+
+  # the minimum number of connections to keep open
+  minSize: 8
+
+  # the maximum number of connections to keep open
+  maxSize: 256
+
+  # whether or not idle connections should be validated
+  checkConnectionWhileIdle: false
+
+  # disable comments in SQL queries
+  autoCommentsEnabled: false
+
+  # disable autocommit in the JDBC driver
+  autoCommitByDefault: false

+ 0 - 2
frameworks/Java/dropwizard/hello-world-mongo.yml

@@ -7,11 +7,9 @@ server:
     useServerHeader: true
     useServerHeader: true
     # There is no proxy in front of the server
     # There is no proxy in front of the server
     useForwardedHeaders: false
     useForwardedHeaders: false
-
   # Test requirements forbid gzip compression of the replies
   # Test requirements forbid gzip compression of the replies
   gzip:
   gzip:
     enabled: false
     enabled: false
-
   requestLog:
   requestLog:
     appenders: []
     appenders: []
 
 

+ 9 - 2
frameworks/Java/dropwizard/hello-world-mysql.yml

@@ -7,11 +7,9 @@ server:
     useServerHeader: true
     useServerHeader: true
     # There is no proxy in front of the server
     # There is no proxy in front of the server
     useForwardedHeaders: false
     useForwardedHeaders: false
-
   # Test requirements forbid gzip compression of the replies
   # Test requirements forbid gzip compression of the replies
   gzip:
   gzip:
     enabled: false
     enabled: false
-
   requestLog:
   requestLog:
     appenders: []
     appenders: []
 
 
@@ -39,6 +37,9 @@ database:
   # the maximum amount of time to wait on an empty pool before throwing an exception
   # the maximum amount of time to wait on an empty pool before throwing an exception
   maxWaitForConnection: 1s
   maxWaitForConnection: 1s
 
 
+  # the initial number of connections
+  initialSize: 8
+
   # the minimum number of connections to keep open
   # the minimum number of connections to keep open
   minSize: 8
   minSize: 8
 
 
@@ -47,3 +48,9 @@ database:
 
 
   # whether or not idle connections should be validated
   # whether or not idle connections should be validated
   checkConnectionWhileIdle: false
   checkConnectionWhileIdle: false
+
+  # disable comments in SQL queries
+  autoCommentsEnabled: false
+
+  # disable autocommit in the JDBC driver
+  autoCommitByDefault: false

+ 9 - 2
frameworks/Java/dropwizard/hello-world-postgres.yml

@@ -7,11 +7,9 @@ server:
     useServerHeader: true
     useServerHeader: true
     # There is no proxy in front of the server
     # There is no proxy in front of the server
     useForwardedHeaders: false
     useForwardedHeaders: false
-
   # Test requirements forbid gzip compression of the replies
   # Test requirements forbid gzip compression of the replies
   gzip:
   gzip:
     enabled: false
     enabled: false
-
   requestLog:
   requestLog:
     appenders: []
     appenders: []
 
 
@@ -39,6 +37,9 @@ database:
   # the maximum amount of time to wait on an empty pool before throwing an exception
   # the maximum amount of time to wait on an empty pool before throwing an exception
   maxWaitForConnection: 1s
   maxWaitForConnection: 1s
 
 
+  # the initial number of connections
+  initialSize: 8
+
   # the minimum number of connections to keep open
   # the minimum number of connections to keep open
   minSize: 8
   minSize: 8
 
 
@@ -47,3 +48,9 @@ database:
 
 
   # whether or not idle connections should be validated
   # whether or not idle connections should be validated
   checkConnectionWhileIdle: false
   checkConnectionWhileIdle: false
+
+  # disable comments in SQL queries
+  autoCommentsEnabled: false
+
+  # disable autocommit in the JDBC driver
+  autoCommitByDefault: false

+ 157 - 132
frameworks/Java/dropwizard/pom.xml

@@ -1,141 +1,166 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <?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"
 <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/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
+	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>com.xekm</groupId>
-    <artifactId>hello-world</artifactId>
-    <version>0.0.1-SNAPSHOT</version>
+	<groupId>com.xekm</groupId>
+	<artifactId>hello-world</artifactId>
+	<version>0.0.1-SNAPSHOT</version>
 
 
-    <properties>
-        <jdk.version>1.8</jdk.version>
-
-        <dropwizard.version>1.0.3</dropwizard.version>
+	<properties>
+    	<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+	<jdk.version>1.8</jdk.version>
+        <dropwizard.version>1.1.1</dropwizard.version>
         <mysql-connector-java.version>5.1.38</mysql-connector-java.version>
         <mysql-connector-java.version>5.1.38</mysql-connector-java.version>
-        <mongojack.version>2.6.1</mongojack.version>
-        <postgres-jdbc.version>9.4.1208</postgres-jdbc.version>
-
-        <main.class>com.example.helloworld.HelloWorldService</main.class>
-    </properties>
-
+        <mongojack.version>2.7.0</mongojack.version>
+        <postgres-jdbc.version>42.1.1</postgres-jdbc.version>
+	<main.class>com.example.helloworld.HelloWorldService</main.class>
+	</properties>
 
 
-    <profiles>
-        <profile>
-            <id>mysql</id>
-            <dependencies>
-                <dependency>
-                    <groupId>mysql</groupId>
-                    <artifactId>mysql-connector-java</artifactId>
-                    <version>${mysql-connector-java.version}</version>
-                </dependency>
-            </dependencies>
-        </profile>
-        <profile>
-            <id>mongo</id>
-            <properties>
-                <main.class>com.example.helloworld.HelloMongoService</main.class>
-            </properties>
-        </profile>
-        <profile>
-            <id>postgres</id>
-            <dependencies>
-                <dependency>
-                    <groupId>org.postgresql</groupId>
-                    <artifactId>postgresql</artifactId>
-                    <version>${postgres-jdbc.version}</version>
-                </dependency>
-            </dependencies>
-        </profile>
-    </profiles>
+	<profiles>
+		<profile>
+			<id>mysql</id>
+			<dependencies>
+				<dependency>
+					<groupId>mysql</groupId>
+					<artifactId>mysql-connector-java</artifactId>
+					<version>${mysql-connector-java.version}</version>
+				</dependency>
+			</dependencies>
+		</profile>
+		<profile>
+			<id>mongo</id>
+			<properties>
+				<main.class>com.example.helloworld.HelloMongoService</main.class>
+			</properties>
+		</profile>
+		<profile>
+			<id>postgres</id>
+			<dependencies>
+				<dependency>
+					<groupId>org.postgresql</groupId>
+					<artifactId>postgresql</artifactId>
+					<version>${postgres-jdbc.version}</version>
+				</dependency>
+			</dependencies>
+		</profile>
+		<profile>
+			<id>jdbi</id>
+			<properties>
+				<main.class>com.example.helloworld.HelloJDBIService</main.class>
+			</properties>
+		</profile>
+	</profiles>
 
 
-    <dependencies>
-        <dependency>
-            <groupId>io.dropwizard</groupId>
-            <artifactId>dropwizard-core</artifactId>
-            <version>${dropwizard.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>io.dropwizard</groupId>
-            <artifactId>dropwizard-hibernate</artifactId>
-            <version>${dropwizard.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>io.dropwizard</groupId>
-            <artifactId>dropwizard-views-mustache</artifactId>
-            <version>${dropwizard.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.mongojack</groupId>
-            <artifactId>mongojack</artifactId>
-            <version>${mongojack.version}</version>
-            <exclusions>
-                <exclusion>
-                    <groupId>com.fasterxml.jackson.core</groupId>
-                    <artifactId>jackson-databind</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-    </dependencies>
+	<dependencies>
+		<dependency>
+			<groupId>io.dropwizard</groupId>
+			<artifactId>dropwizard-core</artifactId>
+			<version>${dropwizard.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>io.dropwizard</groupId>
+			<artifactId>dropwizard-hibernate</artifactId>
+			<version>${dropwizard.version}</version>
+			<exclusions>
+				<exclusion>
+					<groupId>org.apache.geronimo.specs</groupId>
+					<artifactId>geronimo-jta_1.1_spec</artifactId>
+				</exclusion>
+				<exclusion>
+					<groupId>javax.transaction</groupId>
+					<artifactId>jta</artifactId>
+				</exclusion>
+			</exclusions>
+		</dependency>
+		<dependency>
+			<groupId>io.dropwizard</groupId>
+			<artifactId>dropwizard-jdbi</artifactId>
+			<version>${dropwizard.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>io.dropwizard</groupId>
+			<artifactId>dropwizard-views-mustache</artifactId>
+			<version>${dropwizard.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>org.mongojack</groupId>
+			<artifactId>mongojack</artifactId>
+			<version>${mongojack.version}</version>
+			<exclusions>
+				<exclusion>
+					<groupId>com.fasterxml.jackson.core</groupId>
+					<artifactId>jackson-databind</artifactId>
+				</exclusion>
+				<exclusion>
+					<groupId>javax.persistence</groupId>
+					<artifactId>persistence-api</artifactId>
+				</exclusion>
+			</exclusions>
+		</dependency>
+	</dependencies>
 
 
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <version>2.3.2</version>
-                <configuration>
-                    <source>${jdk.version}</source>
-                    <target>${jdk.version}</target>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-jar-plugin</artifactId>
-                <version>2.3.2</version>
-                <configuration>
-                    <archive>
-                        <manifest>
-                            <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
-                        </manifest>
-                    </archive>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-shade-plugin</artifactId>
-                <version>1.6</version>
-                <configuration>
-                    <createDependencyReducedPom>true</createDependencyReducedPom>
-                    <filters>
-                        <filter>
-                            <artifact>*:*</artifact>
-                            <excludes>
-                                <exclude>META-INF/*.SF</exclude>
-                                <exclude>META-INF/*.DSA</exclude>
-                                <exclude>META-INF/*.RSA</exclude>
-                            </excludes>
-                        </filter>
-                    </filters>
-                </configuration>
-                <executions>
-                    <execution>
-                        <phase>package</phase>
-                        <goals>
-                            <goal>shade</goal>
-                        </goals>
-                        <configuration>
-                            <transformers>
-                                <transformer
-                                        implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
-                                <transformer
-                                        implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
-                                    <mainClass>${main.class}</mainClass>
-                                </transformer>
-                            </transformers>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-    </build>
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<version>2.3.2</version>
+				<configuration>
+					<source>${jdk.version}</source>
+					<target>${jdk.version}</target>
+					<optimize>true</optimize>
+                                        <debug>false</debug>
+				</configuration>
+			</plugin>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-jar-plugin</artifactId>
+				<version>2.3.2</version>
+				<configuration>
+					<archive>
+						<manifest>
+							<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+						</manifest>
+					</archive>
+				</configuration>
+			</plugin>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-shade-plugin</artifactId>
+				<version>1.6</version>
+				<configuration>
+					<createDependencyReducedPom>true</createDependencyReducedPom>
+					<filters>
+						<filter>
+							<artifact>*:*</artifact>
+							<excludes>
+								<exclude>META-INF/*.SF</exclude>
+								<exclude>META-INF/*.DSA</exclude>
+								<exclude>META-INF/*.RSA</exclude>
+							</excludes>
+						</filter>
+					</filters>
+				</configuration>
+				<executions>
+					<execution>
+						<phase>package</phase>
+						<goals>
+							<goal>shade</goal>
+						</goals>
+						<configuration>
+							<transformers>
+								<transformer
+									implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
+								<transformer
+									implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+									<mainClass>${main.class}</mainClass>
+								</transformer>
+							</transformers>
+						</configuration>
+					</execution>
+				</executions>
+			</plugin>
+		</plugins>
+	</build>
 </project>
 </project>

+ 7 - 0
frameworks/Java/dropwizard/setup_jdbi_postgres.sh

@@ -0,0 +1,7 @@
+#!/bin/bash
+
+fw_depends postgresql java maven
+
+mvn -P postgres,jdbi clean package
+
+java -jar target/hello-world-0.0.1-SNAPSHOT.jar server hello-world-jdbi-postgres.yml &

+ 38 - 0
frameworks/Java/dropwizard/src/main/java/com/example/helloworld/HelloJDBIService.java

@@ -0,0 +1,38 @@
+package com.example.helloworld;
+
+import io.dropwizard.Application;
+import io.dropwizard.jdbi.DBIFactory;
+import io.dropwizard.jdbi.bundles.DBIExceptionsBundle;
+import io.dropwizard.setup.Bootstrap;
+import io.dropwizard.setup.Environment;
+import io.dropwizard.views.ViewBundle;
+
+import org.skife.jdbi.v2.DBI;
+
+import com.example.helloworld.config.HelloWorldConfiguration;
+import com.example.helloworld.db.jdbi.FortuneJDBIImpl;
+import com.example.helloworld.db.jdbi.WorldRepository;
+import com.example.helloworld.resources.FortuneResource;
+import com.example.helloworld.resources.WorldResource;
+
+public class HelloJDBIService extends Application<HelloWorldConfiguration> {
+	public static void main(String[] args) throws Exception {
+        new HelloJDBIService().run(args);
+    }
+
+    @Override
+    public void initialize(Bootstrap<HelloWorldConfiguration> bootstrap) {
+        bootstrap.addBundle(new ViewBundle<>());
+        bootstrap.addBundle(new DBIExceptionsBundle()); // Provides automatic unwrapping of SQLException and DBIException
+    }
+
+    @Override
+    public void run(HelloWorldConfiguration config, Environment environment) throws ClassNotFoundException {
+    	final DBIFactory factory = new DBIFactory();
+        final DBI jdbi = factory.build(environment, config.getDatabaseConfiguration(), "RDBMS");
+    	
+        // Test type 1: JSON serialization and Test type 6: Plaintext are tested against HelloWorldService class
+        environment.jersey().register(new WorldResource(new WorldRepository(jdbi))); // Test types 2, 3 & 5: Single database query, Multiple database queries & Database updates
+        environment.jersey().register(new FortuneResource(jdbi.onDemand(FortuneJDBIImpl.class))); // Test type 4: Fortunes 
+    }
+}

+ 1 - 1
frameworks/Java/dropwizard/src/main/java/com/example/helloworld/HelloWorldService.java

@@ -34,7 +34,7 @@ public class HelloWorldService extends Application<HelloWorldConfiguration> {
     @Override
     @Override
     public void initialize(Bootstrap<HelloWorldConfiguration> bootstrap) {
     public void initialize(Bootstrap<HelloWorldConfiguration> bootstrap) {
         bootstrap.addBundle(hibernate);
         bootstrap.addBundle(hibernate);
-        bootstrap.addBundle(new ViewBundle());
+        bootstrap.addBundle(new ViewBundle<>());
     }
     }
 
 
     @Override
     @Override

+ 5 - 10
frameworks/Java/dropwizard/src/main/java/com/example/helloworld/db/hibernate/WorldHibernateImpl.java

@@ -1,11 +1,12 @@
 package com.example.helloworld.db.hibernate;
 package com.example.helloworld.db.hibernate;
 
 
+import io.dropwizard.hibernate.AbstractDAO;
+
+import org.hibernate.SessionFactory;
+
 import com.example.helloworld.db.WorldDAO;
 import com.example.helloworld.db.WorldDAO;
 import com.example.helloworld.db.model.World;
 import com.example.helloworld.db.model.World;
 import com.example.helloworld.resources.Helper;
 import com.example.helloworld.resources.Helper;
-import io.dropwizard.hibernate.AbstractDAO;
-import org.hibernate.SessionFactory;
-import org.hibernate.Transaction;
 
 
 public class WorldHibernateImpl extends AbstractDAO<World> implements WorldDAO {
 public class WorldHibernateImpl extends AbstractDAO<World> implements WorldDAO {
     public WorldHibernateImpl(SessionFactory factory) {
     public WorldHibernateImpl(SessionFactory factory) {
@@ -25,15 +26,9 @@ public class WorldHibernateImpl extends AbstractDAO<World> implements WorldDAO {
     @Override
     @Override
     public World[] updatesQueries(int totalQueries) {
     public World[] updatesQueries(int totalQueries) {
         final World[] worlds = new World[totalQueries];
         final World[] worlds = new World[totalQueries];
+        //TODO implement write batching
         for (int i = 0; i < totalQueries; i++) {
         for (int i = 0; i < totalQueries; i++) {
-            Transaction transaction = currentSession().beginTransaction();
-            try {
                 worlds[i] = findAndModify(Helper.randomWorld(), Helper.randomWorld());
                 worlds[i] = findAndModify(Helper.randomWorld(), Helper.randomWorld());
-                transaction.commit();
-            } catch (Exception e) {
-                transaction.rollback();
-                throw new RuntimeException(e);
-            }
         }
         }
         return worlds;
         return worlds;
     }
     }

+ 17 - 0
frameworks/Java/dropwizard/src/main/java/com/example/helloworld/db/jdbi/FortuneJDBIImpl.java

@@ -0,0 +1,17 @@
+package com.example.helloworld.db.jdbi;
+
+import java.util.List;
+
+import org.skife.jdbi.v2.sqlobject.SqlQuery;
+import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
+import org.skife.jdbi.v2.sqlobject.mixins.Transactional;
+
+import com.example.helloworld.db.FortuneDAO;
+import com.example.helloworld.db.mappers.FortuneMapper;
+import com.example.helloworld.db.model.Fortune;
+
+public abstract class FortuneJDBIImpl implements Transactional<FortuneJDBIImpl>, FortuneDAO {
+	@SqlQuery("select id, message from fortune")
+	@RegisterMapper(FortuneMapper.class)
+	public abstract List<Fortune> list();
+}

+ 20 - 0
frameworks/Java/dropwizard/src/main/java/com/example/helloworld/db/jdbi/WorldJDBIImpl.java

@@ -0,0 +1,20 @@
+package com.example.helloworld.db.jdbi;
+
+import org.skife.jdbi.v2.sqlobject.Bind;
+import org.skife.jdbi.v2.sqlobject.BindBean;
+import org.skife.jdbi.v2.sqlobject.SqlQuery;
+import org.skife.jdbi.v2.sqlobject.SqlUpdate;
+import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
+import org.skife.jdbi.v2.sqlobject.mixins.Transactional;
+
+import com.example.helloworld.db.mappers.WorldMapper;
+import com.example.helloworld.db.model.World;
+
+@RegisterMapper(WorldMapper.class)
+public abstract class WorldJDBIImpl implements Transactional<WorldJDBIImpl>, AutoCloseable  {
+	@SqlQuery("select id, randomNumber from world where id = :id")
+	public abstract World findById(@Bind("id") int id);
+
+	@SqlUpdate("update world set randomNumber = :p.randomNumber where id = :p.id")
+	public abstract long update(@BindBean("p") World world);
+}

+ 63 - 0
frameworks/Java/dropwizard/src/main/java/com/example/helloworld/db/jdbi/WorldRepository.java

@@ -0,0 +1,63 @@
+package com.example.helloworld.db.jdbi;
+
+import org.skife.jdbi.v2.DBI;
+
+import com.example.helloworld.db.WorldDAO;
+import com.example.helloworld.db.model.World;
+import com.example.helloworld.resources.Helper;
+
+public class WorldRepository implements WorldDAO {
+	private DBI jdbi;
+
+	public WorldRepository(DBI jdbi) {
+		super();
+		this.jdbi = jdbi;
+	}
+
+	@Override
+	public World findById(int id) {
+		try (WorldJDBIImpl dao = jdbi.open(WorldJDBIImpl.class)) {
+			return dao.findById(id);
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	public World[] findById(int[] ids) {
+		final World[] worlds = new World[ids.length];
+		try (WorldJDBIImpl dao = jdbi.open(WorldJDBIImpl.class)) {
+			return dao.inTransaction((conn, status) -> {
+				for (int i = 0; i < ids.length; i++) {
+					worlds[i] = dao.findById(ids[i]);
+				}
+				return worlds;
+			});
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	@Override
+	public World findAndModify(int id, int newRandomNumber) {
+		throw new RuntimeException("Don't call this");
+	}
+
+	@Override
+	public World[] updatesQueries(int totalQueries) {
+		final World[] updates = new World[totalQueries];
+		try (WorldJDBIImpl dao = jdbi.open(WorldJDBIImpl.class)) {
+				for (int i = 0; i < totalQueries; i++) {
+					updates[i] = dao.inTransaction((conn, status) -> {
+						final World world = dao.findById(Helper.randomWorld());
+						world.setRandomNumber(Helper.randomWorld());
+						dao.update(world);
+						return world;
+					});
+				}
+				return updates;
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+}

+ 16 - 0
frameworks/Java/dropwizard/src/main/java/com/example/helloworld/db/mappers/FortuneMapper.java

@@ -0,0 +1,16 @@
+package com.example.helloworld.db.mappers;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import org.skife.jdbi.v2.StatementContext;
+import org.skife.jdbi.v2.tweak.ResultSetMapper;
+
+import com.example.helloworld.db.model.Fortune;
+
+public class FortuneMapper implements ResultSetMapper<Fortune> {
+	public Fortune map(int index, ResultSet r, StatementContext ctx)
+			throws SQLException {
+		return new Fortune(r.getInt("id"), r.getString("message"));
+	}
+}

+ 16 - 0
frameworks/Java/dropwizard/src/main/java/com/example/helloworld/db/mappers/WorldMapper.java

@@ -0,0 +1,16 @@
+package com.example.helloworld.db.mappers;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import org.skife.jdbi.v2.StatementContext;
+import org.skife.jdbi.v2.tweak.ResultSetMapper;
+
+import com.example.helloworld.db.model.World;
+
+public class WorldMapper implements ResultSetMapper<World> {
+	public World map(int index, ResultSet r, StatementContext ctx)
+			throws SQLException {
+		return new World(r.getInt("id"), r.getInt("randomNumber"));
+	}
+}

+ 10 - 3
frameworks/Java/dropwizard/src/main/java/com/example/helloworld/db/model/Fortune.java

@@ -18,10 +18,17 @@ public class Fortune implements Comparable<Fortune> {
 
 
     @SuppressWarnings("unused")
     @SuppressWarnings("unused")
     public Fortune() {}
     public Fortune() {}
-
+    
     public Fortune(String message) {
     public Fortune(String message) {
-        this.message = message;
-    }
+		super();
+		this.message = message;
+	}
+    
+    public Fortune(int id, String message) {
+		super();
+		this.id = id;
+		this.message = message;
+	}
 
 
     public int getId() {
     public int getId() {
         return id;
         return id;

+ 5 - 0
frameworks/Java/dropwizard/src/main/java/com/example/helloworld/db/model/World.java

@@ -21,6 +21,11 @@ public class World {
 
 
     public World() {
     public World() {
     }
     }
+    
+    public World(int id, int randomNumber) {
+    	this.id = id;
+    	this.randomNumber = randomNumber;
+    }
 
 
     public int getId() {
     public int getId() {
         return id;
         return id;

+ 19 - 19
frameworks/Java/dropwizard/src/main/java/com/example/helloworld/resources/FortuneResource.java

@@ -1,37 +1,37 @@
 package com.example.helloworld.resources;
 package com.example.helloworld.resources;
 
 
-import com.example.helloworld.db.FortuneDAO;
-import com.example.helloworld.db.model.Fortune;
-import com.example.helloworld.resources.views.FortuneView;
-import com.google.common.collect.Lists;
 import io.dropwizard.hibernate.UnitOfWork;
 import io.dropwizard.hibernate.UnitOfWork;
 
 
+import java.util.Collections;
+import java.util.List;
+
 import javax.ws.rs.GET;
 import javax.ws.rs.GET;
 import javax.ws.rs.Path;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.MediaType;
-import java.util.Collections;
-import java.util.List;
+
+import com.example.helloworld.db.FortuneDAO;
+import com.example.helloworld.db.model.Fortune;
+import com.example.helloworld.resources.views.FortuneView;
 
 
 @Path("/fortunes")
 @Path("/fortunes")
 @Produces(MediaType.TEXT_HTML + ";charset=UTF-8")
 @Produces(MediaType.TEXT_HTML + ";charset=UTF-8")
 public class FortuneResource {
 public class FortuneResource {
 
 
-    private final FortuneDAO fortuneDAO;
+	private final FortuneDAO fortuneDAO;
 
 
-    public FortuneResource(FortuneDAO fortuneDAO) {
-        this.fortuneDAO = fortuneDAO;
-    }
+	public FortuneResource(FortuneDAO fortuneDAO) {
+		this.fortuneDAO = fortuneDAO;
+	}
 
 
-    @GET
-    @UnitOfWork
-    public FortuneView dbTest() {
-        final List<Fortune> fortunes = Lists.newArrayListWithExpectedSize(32);
+	@GET
+	@UnitOfWork(transactional = false) // Needed only for Hibernate - not for Mongo or JDBI
+	public FortuneView dbTest() {
+		final List<Fortune> fortunes = fortuneDAO.list();
 
 
-        fortunes.addAll(fortuneDAO.list());
-        fortunes.add(new Fortune("Additional fortune added at request time."));
+		fortunes.add(new Fortune("Additional fortune added at request time."));
 
 
-        Collections.sort(fortunes);
-        return new FortuneView(fortunes);
-    }
+		Collections.sort(fortunes);
+		return new FortuneView(fortunes);
+	}
 }
 }

+ 8 - 5
frameworks/Java/dropwizard/src/main/java/com/example/helloworld/resources/Helper.java

@@ -1,7 +1,6 @@
 package com.example.helloworld.resources;
 package com.example.helloworld.resources;
 
 
-import com.google.common.base.Optional;
-
+import java.util.Optional;
 import java.util.concurrent.ThreadLocalRandom;
 import java.util.concurrent.ThreadLocalRandom;
 
 
 /**
 /**
@@ -17,14 +16,18 @@ public final class Helper {
         if (!queries.isPresent()) {
         if (!queries.isPresent()) {
             return 1;
             return 1;
         }
         }
-        try {
-            int parsedValue = Integer.parseInt(queries.get());
+        return getQueries(queries.get());
+    }
+
+    static int getQueries(String queries) {
+    	try {
+            int parsedValue = Integer.parseInt(queries);
             return Math.min(500, Math.max(1, parsedValue));
             return Math.min(500, Math.max(1, parsedValue));
         } catch (NumberFormatException e) {
         } catch (NumberFormatException e) {
             return 1;
             return 1;
         }
         }
     }
     }
-
+    
     public static int randomWorld() {
     public static int randomWorld() {
         return 1 + ThreadLocalRandom.current().nextInt(10000);
         return 1 + ThreadLocalRandom.current().nextInt(10000);
     }
     }

+ 34 - 29
frameworks/Java/dropwizard/src/main/java/com/example/helloworld/resources/WorldResource.java

@@ -1,8 +1,7 @@
 package com.example.helloworld.resources;
 package com.example.helloworld.resources;
 
 
-import com.example.helloworld.db.WorldDAO;
-import com.example.helloworld.db.model.World;
-import com.google.common.base.Optional;
+import java.util.Optional;
+
 import io.dropwizard.hibernate.UnitOfWork;
 import io.dropwizard.hibernate.UnitOfWork;
 
 
 import javax.ws.rs.GET;
 import javax.ws.rs.GET;
@@ -11,34 +10,40 @@ import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.MediaType;
 
 
+import com.example.helloworld.db.WorldDAO;
+import com.example.helloworld.db.model.World;
+
 @Path("/db")
 @Path("/db")
 @Produces(MediaType.APPLICATION_JSON)
 @Produces(MediaType.APPLICATION_JSON)
 public class WorldResource {
 public class WorldResource {
-    private final WorldDAO worldDAO;
-
-    public WorldResource(WorldDAO worldDAO) {
-        this.worldDAO = worldDAO;
-    }
+	private final WorldDAO worldDAO;
 
 
-    @GET
-    @UnitOfWork
-    public Object dbTest(@QueryParam("queries") Optional<String> queries) {
-        if (queries.isPresent()) {
-            int totalQueries = Helper.getQueries(queries);
-            final World[] worlds = new World[totalQueries];
-            for (int i = 0; i < totalQueries; i++) {
-                worlds[i] = worldDAO.findById(Helper.randomWorld());
-            }
-            return worlds;
-        } else {
-            return worldDAO.findById(Helper.randomWorld());
-        }
-    }
+	public WorldResource(WorldDAO worldDAO) {
+		this.worldDAO = worldDAO;
+	}
+	
+	@GET
+	@UnitOfWork(transactional = false) // Needed only for Hibernate - not for Mongo or JDBI
+	public Object db() {
+		return worldDAO.findById(Helper.randomWorld());
+	}
+	
+	@GET
+	@Path("/query")
+	@UnitOfWork(transactional = false) // Needed only for Hibernate - not for Mongo or JDBI
+	public Object dbTest(@QueryParam("queries") String queries) {
+		int totalQueries = Helper.getQueries(queries); // Optional check is done inside
+		final World[] worlds = new World[totalQueries];
+		for (int i = 0; i < totalQueries; i++) {
+			worlds[i] = worldDAO.findById(Helper.randomWorld());
+		}
+		return worlds;
+	}
 
 
-    @GET
-    @Path("/update")
-    @UnitOfWork(transactional = false)
-    public World[] updateTest(@QueryParam("queries") Optional<String> queries) {
-        return worldDAO.updatesQueries(Helper.getQueries(queries));
-    }
-}
+	@GET
+	@Path("/update")
+	@UnitOfWork(transactional = false) // Needed only for Hibernate - not for Mongo or JDBI
+	public World[] updateTest(@QueryParam("queries") Optional<String> queries) {
+		return worldDAO.updatesQueries(Helper.getQueries(queries));
+	}
+}