From 66e1a070ed075c140a72950068d66a0648cea659 Mon Sep 17 00:00:00 2001 From: Donovan Muller Date: Mon, 27 Oct 2014 14:42:22 +0200 Subject: [PATCH] Added the remaining tests. Bumped Play version to 2.3.6. Added HikariCP benchmark config. --- frameworks/Java/play2-java/benchmark_config | 29 +++- frameworks/Java/play2-java/generate_config.py | 22 +-- .../play2-java-jpa-hikaricp/.gitignore | 29 ++++ .../play2-java-jpa-hikaricp/README.md | 40 +++++ .../app/controllers/Application.java | 151 ++++++++++++++++++ .../app/models/Fortune.java | 34 ++++ .../app/models/World.java | 38 +++++ .../app/utils/Headers.java | 21 +++ .../app/utils/Predicate.java | 8 + .../app/utils/Predicated.java | 26 +++ .../app/utils/PredicatedAction.java | 23 +++ .../app/views/fortunes.scala.html | 16 ++ .../app/views/main.scala.html | 12 ++ .../play2-java-jpa-hikaricp/build.sbt | 17 ++ .../conf/META-INF/persistence.xml | 14 ++ .../conf/application.conf | 97 +++++++++++ .../play2-java-jpa-hikaricp/conf/play.plugins | 1 + .../play2-java-jpa-hikaricp/conf/routes | 13 ++ .../project/build.properties | 1 + .../project/plugins.sbt | 4 + .../play2-java-jpa-hikaricp/source_code | 11 ++ .../Java/play2-java/play2-java-jpa/README.md | 24 ++- .../app/controllers/Application.java | 61 +++++-- .../play2-java-jpa/app/models/Fortune.java | 34 ++++ .../play2-java-jpa/app/models/World.java | 27 +++- .../play2-java-jpa/app/utils/Headers.java | 21 +++ .../app/views/fortunes.scala.html | 16 ++ .../play2-java-jpa/app/views/main.scala.html | 12 ++ .../Java/play2-java/play2-java-jpa/build.sbt | 2 +- .../play2-java/play2-java-jpa/conf/routes | 4 +- .../play2-java-jpa/project/plugins.sbt | 2 +- .../play2-java/play2-java-jpa/source_code | 2 + .../play2-java/setup_java_jpa_hikaricp.py | 6 + 33 files changed, 781 insertions(+), 37 deletions(-) create mode 100644 frameworks/Java/play2-java/play2-java-jpa-hikaricp/.gitignore create mode 100644 frameworks/Java/play2-java/play2-java-jpa-hikaricp/README.md create mode 100644 frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/controllers/Application.java create mode 100644 frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/models/Fortune.java create mode 100644 frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/models/World.java create mode 100644 frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/utils/Headers.java create mode 100644 frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/utils/Predicate.java create mode 100644 frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/utils/Predicated.java create mode 100644 frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/utils/PredicatedAction.java create mode 100644 frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/views/fortunes.scala.html create mode 100644 frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/views/main.scala.html create mode 100644 frameworks/Java/play2-java/play2-java-jpa-hikaricp/build.sbt create mode 100644 frameworks/Java/play2-java/play2-java-jpa-hikaricp/conf/META-INF/persistence.xml create mode 100644 frameworks/Java/play2-java/play2-java-jpa-hikaricp/conf/application.conf create mode 100644 frameworks/Java/play2-java/play2-java-jpa-hikaricp/conf/play.plugins create mode 100644 frameworks/Java/play2-java/play2-java-jpa-hikaricp/conf/routes create mode 100644 frameworks/Java/play2-java/play2-java-jpa-hikaricp/project/build.properties create mode 100644 frameworks/Java/play2-java/play2-java-jpa-hikaricp/project/plugins.sbt create mode 100644 frameworks/Java/play2-java/play2-java-jpa-hikaricp/source_code create mode 100644 frameworks/Java/play2-java/play2-java-jpa/app/models/Fortune.java create mode 100644 frameworks/Java/play2-java/play2-java-jpa/app/utils/Headers.java create mode 100644 frameworks/Java/play2-java/play2-java-jpa/app/views/fortunes.scala.html create mode 100644 frameworks/Java/play2-java/play2-java-jpa/app/views/main.scala.html create mode 100644 frameworks/Java/play2-java/setup_java_jpa_hikaricp.py diff --git a/frameworks/Java/play2-java/benchmark_config b/frameworks/Java/play2-java/benchmark_config index 3c227e4eb3f..9714730ef8b 100644 --- a/frameworks/Java/play2-java/benchmark_config +++ b/frameworks/Java/play2-java/benchmark_config @@ -56,8 +56,33 @@ "versus": "netty", "port": "9000", "db_url": "/db", - "query_url": "/queries?queries=" + "query_url": "/queries?queries=", + "fortune_url": "/fortunes", + "update_url": "/update?queries=", + "plaintext_url": "/plaintext" + }, + "java-jpa-hikaricp": { + "display_name": "play2-java-jpa-hikaricp", + "setup_file": "setup_java_jpa_hikaricp", + "framework": "play2", + "language": "Java", + "orm": "Full", + "os": "Linux", + "database": "MySQL", + "approach": "Realistic", + "classification": "Fullstack", + "platform": "Netty", + "webserver": "None", + "database_os": "Linux", + "notes": "", + "versus": "netty", + "port": "9000", + "db_url": "/db", + "query_url": "/queries?queries=", + "fortune_url": "/fortunes", + "update_url": "/update?queries=", + "plaintext_url": "/plaintext" } } ] -} +} \ No newline at end of file diff --git a/frameworks/Java/play2-java/generate_config.py b/frameworks/Java/play2-java/generate_config.py index 616bbbb0373..ba5355bf9ab 100644 --- a/frameworks/Java/play2-java/generate_config.py +++ b/frameworks/Java/play2-java/generate_config.py @@ -9,12 +9,13 @@ # Format is: (language, orm, (opsys, ...), (test, ...)) # See the dir_name logic below to see the directory name for each test application. configurations = [ - ('Java', None, ['Linux'], ['json']), - ('Java', 'Ebean', ['Linux'], ['db', 'query']), - ('Java', 'JPA', ['Linux'], ['db', 'query']), - ('Scala', None, ['Linux'], ['json']), - ('Scala', 'Anorm', ['Linux', 'Windows'], ['db', 'query', 'fortune', 'update']), - ('Scala', 'Slick', ['Linux'], ['db', 'query', 'fortune', 'update']), + ('Java', None, ['Linux'], ['json']), + ('Java', 'Ebean', ['Linux'], ['db', 'query']), + ('Java', 'JPA', ['Linux'], ['db', 'query', 'fortune', 'update', 'plaintext']), + ('Java', 'JPA HikariCP', ['Linux'], ['db', 'query', 'fortune', 'update', 'plaintext']), + ('Scala', None, ['Linux'], ['json']), + ('Scala', 'Anorm', ['Linux', 'Windows'], ['db', 'query', 'fortune', 'update']), + ('Scala', 'Slick', ['Linux'], ['db', 'query', 'fortune', 'update']), ] # All play2 test applications must use the same URLs. @@ -24,6 +25,7 @@ 'query': '/queries?queries=', 'fortune': '/fortunes', 'update': '/update?queries=', + 'plaintext': '/plaintext', } langs = { @@ -41,8 +43,8 @@ def frameworksPath(): lang_test_configs[lang] = collections.OrderedDict() for lang, orm, opsyses, tests in configurations: - dir_name = 'play2-' + lang.lower() + (('-'+orm.lower()) if orm else '') - setup_name = 'setup_' + lang.lower() + (('_'+orm.lower()) if orm else '') + dir_name = 'play2-' + lang.lower() + (('-'+orm.replace(' ', '-').lower()) if orm else '') + setup_name = 'setup_' + lang.lower() + (('_'+orm.replace(' ', '_').lower()) if orm else '') setup_path = os.path.join(pathForLang(lang), setup_name+'.py') print 'Generating', setup_path @@ -57,9 +59,9 @@ def frameworksPath(): for opsys in opsyses: if len(opsyses) == 1: - test_name = lang.lower() + (('-'+orm.lower()) if orm else '') + test_name = lang.lower() + (('-'+orm.replace(' ', '-').lower()) if orm else '') else: - test_name = lang.lower() + (('-'+orm.lower()) if orm else '') + '-'+opsys.lower() + test_name = lang.lower() + (('-'+orm.replace(' ', '-').lower()) if orm else '') + '-'+opsys.lower() test_config_json = collections.OrderedDict([ ('display_name', 'play2-'+test_name), ('setup_file', setup_name), diff --git a/frameworks/Java/play2-java/play2-java-jpa-hikaricp/.gitignore b/frameworks/Java/play2-java/play2-java-jpa-hikaricp/.gitignore new file mode 100644 index 00000000000..b561d3b75b8 --- /dev/null +++ b/frameworks/Java/play2-java/play2-java-jpa-hikaricp/.gitignore @@ -0,0 +1,29 @@ +logs +project/project +project/target +target +tmp +.history +dist + +# Ignore all dotfiles... +.* +# except for .gitignore +!.gitignore + +# Ignore Play! working directory # +db +eclipse +lib +log +logs +modules +precompiled +project/project +project/target +target +tmp +test-result +server.pid +*.iml +*.eml \ No newline at end of file diff --git a/frameworks/Java/play2-java/play2-java-jpa-hikaricp/README.md b/frameworks/Java/play2-java/play2-java-jpa-hikaricp/README.md new file mode 100644 index 00000000000..c210444400e --- /dev/null +++ b/frameworks/Java/play2-java/play2-java-jpa-hikaricp/README.md @@ -0,0 +1,40 @@ +#Play Benchmarking Test + +This is the Play portion of a [benchmarking test suite](../) comparing a variety of web development platforms. + +### JSON Encoding Test + +* [JSON test controller](app/controllers/Application.java) + +### Data-Store/Database Mapping Test + +* [Database test controller](app/controllers/Application.java) +* [Database World test model](app/models/World.java) +* [Database Fortune test model](app/models/Fortune.java) + +### Plain Text Test + +* [Plain text test controller](app/controllers/Application.java) + +## Infrastructure Software Versions +The tests were run with: + +* [Java OpenJDK 1.7](http://openjdk.java.net/) +* [Play 2.3.6](http://http://www.playframework.com/) + +## Test URLs +### JSON Encoding Test + +* http://localhost/json + +### Data-Store/Database Mapping Test + +* http://localhost/db +* http://localhost/queries?queries=10 +* http://localhost/fortunes +* http://localhost/update?queries=10 + +### Plain Text Test + +* http://localhost/plaintext + diff --git a/frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/controllers/Application.java b/frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/controllers/Application.java new file mode 100644 index 00000000000..7c3f659dff0 --- /dev/null +++ b/frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/controllers/Application.java @@ -0,0 +1,151 @@ +package controllers; + +import akka.dispatch.ExecutionContexts; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import models.Fortune; +import models.World; +import play.*; +import play.core.NamedThreadFactory; +import play.libs.F; +import play.libs.Json; +import play.mvc.*; + +import scala.concurrent.ExecutionContext; +import utils.Predicate; +import utils.Predicated; +import views.html.*; + +import java.util.*; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +public class Application extends Controller { + + private static final int MAX_QUERIES_PER_REQUEST = 20; + private static final int TEST_DATABASE_ROWS = 10000; + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + private static final int partitionCount = Play.application().configuration().getInt("db.default.partitionCount"); + private static final int maxConnections = + partitionCount * Play.application().configuration().getInt("db.default.maxConnectionsPerPartition"); + private static final int minConnections = + partitionCount * Play.application().configuration().getInt("db.default.minConnectionsPerPartition"); + + private static final ThreadPoolExecutor tpe = new ThreadPoolExecutor(minConnections, maxConnections, + 0L, TimeUnit.MILLISECONDS, + new LinkedBlockingQueue(), + new NamedThreadFactory("dbEc")); + private static final ExecutionContext dbEc = ExecutionContexts.fromExecutorService(tpe); + + public static Result json() { + final ObjectNode result = OBJECT_MAPPER.createObjectNode(); + result.put("message", "Hello World!"); + return ok(result); + } + + // If the thread-pool used by the database grows too large then our server + // is probably struggling, and we should start dropping requests. Set + // the max size of our queue something above the number of concurrent + // connections that we need to handle. + public static class IsDbAvailable implements Predicate { + @Override + public boolean condition() { + return tpe.getQueue().size() <= 1024; + } + } + + @Predicated(predicate = IsDbAvailable.class, failed = SERVICE_UNAVAILABLE) + public static F.Promise db() { + return getRandomWorlds(1).map(new F.Function, Result>() { + @Override + public Result apply(List worlds) { + return ok(Json.toJson(worlds.get(0))); + } + }); + } + + @Predicated(predicate = IsDbAvailable.class, failed = SERVICE_UNAVAILABLE) + public static F.Promise queries(final String queryCountString) { + return getRandomWorlds(queryCount(queryCountString)).map(new F.Function, Result>() { + @Override + public Result apply(List worlds) { + return ok(Json.toJson(worlds)); + } + }); + } + + @Predicated(predicate = IsDbAvailable.class, failed = SERVICE_UNAVAILABLE) + public static F.Promise fortunes() { + return F.Promise.promise(new F.Function0() { + + @Override + public Result apply() throws Throwable { + List fortunes = Fortune.findAll(); + fortunes.add(new Fortune("Additional fortune added at request time.")); + Collections.sort(fortunes, new Comparator() { + @Override + public int compare(Fortune f1, Fortune f2) { + return f1.message.compareTo(f2.message); + } + }); + return ok(views.html.fortunes.render(fortunes)); + } + }, dbEc); + } + + @Predicated(predicate = IsDbAvailable.class, failed = SERVICE_UNAVAILABLE) + public static F.Promise update(final String queryCountString) { + return getRandomWorlds(queryCount(queryCountString)).map(new F.Function, Result>() { + @Override + public Result apply(List worlds) throws Throwable { + Random random = ThreadLocalRandom.current(); + for (World world : worlds) { + world.randomNumber = (long) (random.nextInt(10000) + 1); + } + + worlds = World.save(worlds); + return ok(Json.toJson(worlds)); + } + }); + } + + public static Result plainText() { + return ok("Hello, World!"); + } + + private static int queryCount(String queryCountString) { + int queryCount; + try { + queryCount = Integer.parseInt(queryCountString, 10); + } catch (NumberFormatException e) { + queryCount = 1; + } + if (queryCount < 1) { + queryCount = 1; + } else if (queryCount > 500) { + queryCount = 500; + } + + return queryCount; + } + + private static F.Promise> getRandomWorlds(final int n) { + return F.Promise.promise(new F.Function0>() { + @Override + public List apply() throws Throwable { + Random random = ThreadLocalRandom.current(); + List worlds = new ArrayList(n); + for (int i = 0; i < n; ++i) { + long randomId = random.nextInt(TEST_DATABASE_ROWS) + 1; + World world = World.findById(randomId); + worlds.add(world); + } + return worlds; + } + }, dbEc); + } + +} diff --git a/frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/models/Fortune.java b/frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/models/Fortune.java new file mode 100644 index 00000000000..5d549b33a59 --- /dev/null +++ b/frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/models/Fortune.java @@ -0,0 +1,34 @@ +package models; + +import play.db.jpa.JPA; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.criteria.CriteriaQuery; +import java.util.List; + +@Entity +public class Fortune { + + @Id + public Long id = 0L; + + public String message; + + public Fortune() { + } + + public Fortune(String message) { + this.message = message; + } + + public static List findAll() throws Throwable { + return JPA.withTransaction("default", true, new play.libs.F.Function0>() { + public List apply() { + CriteriaQuery criteria = JPA.em().getCriteriaBuilder().createQuery(Fortune.class); + criteria.select(criteria.from(Fortune.class)); + return JPA.em().createQuery(criteria).getResultList(); + } + }); + } +} \ No newline at end of file diff --git a/frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/models/World.java b/frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/models/World.java new file mode 100644 index 00000000000..1382664f9c2 --- /dev/null +++ b/frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/models/World.java @@ -0,0 +1,38 @@ +package models; + +import play.db.jpa.JPA; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import java.util.List; + +@Entity +public class World { + + @Id + public Long id; + + @Column(name = "randomNumber") + public Long randomNumber; + + public static World findById(final Long id) throws Throwable { + return JPA.withTransaction("default", true, new play.libs.F.Function0() { + public World apply() { + return JPA.em().find(World.class, id); + } + }); + } + + public static List save(final List worlds) throws Throwable { + for (final World world : worlds) { + JPA.withTransaction("default", false, new play.libs.F.Function0() { + public World apply() { + return JPA.em().merge(world); + } + }); + } + + return worlds; + } +} \ No newline at end of file diff --git a/frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/utils/Headers.java b/frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/utils/Headers.java new file mode 100644 index 00000000000..253c4aa70d2 --- /dev/null +++ b/frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/utils/Headers.java @@ -0,0 +1,21 @@ +package utils; + +import org.joda.time.DateTime; +import org.joda.time.format.DateTimeFormat; +import org.joda.time.format.DateTimeFormatter; +import play.libs.F; +import play.mvc.Action; +import play.mvc.Http; +import play.mvc.Result; + +public class Headers extends Action.Simple { + + private static final DateTimeFormatter RFC_1123_DATE_TIME = DateTimeFormat.forPattern("EEE, dd MMM yyyy HH:mm:ss 'GMT'").withZoneUTC(); + + @Override + public F.Promise call(Http.Context context) throws Throwable { + context.response().setHeader("Server", "play2-java-jpa"); + context.response().setHeader("Date", RFC_1123_DATE_TIME.print(new DateTime())); + return delegate.call(context); + } +} diff --git a/frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/utils/Predicate.java b/frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/utils/Predicate.java new file mode 100644 index 00000000000..aa7d159676e --- /dev/null +++ b/frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/utils/Predicate.java @@ -0,0 +1,8 @@ +package utils; + +/** + * Predicates for PredicatedActions. + */ +public interface Predicate { + boolean condition(); +} diff --git a/frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/utils/Predicated.java b/frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/utils/Predicated.java new file mode 100644 index 00000000000..99efc4555f5 --- /dev/null +++ b/frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/utils/Predicated.java @@ -0,0 +1,26 @@ +package utils; + +import play.mvc.With; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Declares a composing action that will check for a condition before deciding on whether to proceed with the request. + */ +@With(PredicatedAction.class) +@Target({ElementType.TYPE, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface Predicated { + /** + * The condition. + */ + Class predicate(); + + /** + * The http status code to return if the condition fails. + */ + int failed(); +} diff --git a/frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/utils/PredicatedAction.java b/frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/utils/PredicatedAction.java new file mode 100644 index 00000000000..93c3427883d --- /dev/null +++ b/frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/utils/PredicatedAction.java @@ -0,0 +1,23 @@ +package utils; + +/** + * A predicated action is one where a condition must be satisfied in order to proceed with the request. If the + * condition is not satisfied then a supplied status result is yielded. + */ + +import play.libs.F; +import play.mvc.Action; +import play.mvc.Http; +import play.mvc.Result; + +public class PredicatedAction extends Action { + @Override + public F.Promise call(final Http.Context ctx) throws Throwable { + final Predicate p = configuration.predicate().newInstance(); + if (p.condition()) { + return delegate.call(ctx); + } else { + return F.Promise.pure(status(configuration.failed())); + } + } +} diff --git a/frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/views/fortunes.scala.html b/frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/views/fortunes.scala.html new file mode 100644 index 00000000000..57a634ef90a --- /dev/null +++ b/frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/views/fortunes.scala.html @@ -0,0 +1,16 @@ +@(fortunes: List[Fortune]) + +@main() { + + + + + + @for(fortune <- fortunes) { + + + + + } +
idmessage
@fortune.id@fortune.message
+} \ No newline at end of file diff --git a/frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/views/main.scala.html b/frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/views/main.scala.html new file mode 100644 index 00000000000..ede13a1641b --- /dev/null +++ b/frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/views/main.scala.html @@ -0,0 +1,12 @@ +@()(content: Html) + + + + + + Fortunes + + + @content + + \ No newline at end of file diff --git a/frameworks/Java/play2-java/play2-java-jpa-hikaricp/build.sbt b/frameworks/Java/play2-java/play2-java-jpa-hikaricp/build.sbt new file mode 100644 index 00000000000..be449490a64 --- /dev/null +++ b/frameworks/Java/play2-java/play2-java-jpa-hikaricp/build.sbt @@ -0,0 +1,17 @@ +name := """play2-java-jpa-hikaricp""" + +version := "1.0-SNAPSHOT" + +lazy val root = (project in file(".")).enablePlugins(PlayJava) + +scalaVersion := "2.11.2" + +libraryDependencies ++= Seq( + javaJdbc, + javaJpa, + "mysql" % "mysql-connector-java" % "5.1.33", + "org.hibernate" % "hibernate-entitymanager" % "4.3.6.Final", + "com.edulify" %% "play-hikaricp" % "1.5.0" +) + +resolvers += Resolver.url("Edulify Repository", url("http://edulify.github.io/modules/releases/"))(Resolver.ivyStylePatterns) diff --git a/frameworks/Java/play2-java/play2-java-jpa-hikaricp/conf/META-INF/persistence.xml b/frameworks/Java/play2-java/play2-java-jpa-hikaricp/conf/META-INF/persistence.xml new file mode 100644 index 00000000000..9ecf780c858 --- /dev/null +++ b/frameworks/Java/play2-java/play2-java-jpa-hikaricp/conf/META-INF/persistence.xml @@ -0,0 +1,14 @@ + + + + org.hibernate.jpa.HibernatePersistenceProvider + DefaultDS + + + + + + \ No newline at end of file diff --git a/frameworks/Java/play2-java/play2-java-jpa-hikaricp/conf/application.conf b/frameworks/Java/play2-java/play2-java-jpa-hikaricp/conf/application.conf new file mode 100644 index 00000000000..b30eee06b40 --- /dev/null +++ b/frameworks/Java/play2-java/play2-java-jpa-hikaricp/conf/application.conf @@ -0,0 +1,97 @@ +# This is the main configuration file for the application. +# ~~~~~ + +# Secret key +# ~~~~~ +# The secret key is used to secure cryptographics functions. +# +# This must be changed for production, but we recommend not changing it in this file. +# +# See http://www.playframework.com/documentation/latest/ApplicationSecret for more details. +application.secret="`o0VB@vXStsF:ffwM5ZZ_r:GYkm96QM[nRUJLpEbI8hwLUdV;N<:UyUWI;lf/XP`" + +# The application languages +# ~~~~~ +application.langs="en" + +# Global object class +# ~~~~~ +# Define the Global object class for this application. +# Default to Global in the root package. +# application.global=Global + +# Router +# ~~~~~ +# Define the Router object to use for this application. +# This router will be looked up first when the application is starting up, +# so make sure this is the entry point. +# Furthermore, it's assumed your route file is named properly. +# So for an application router like `conf/my.application.Router`, +# you may need to define a router file `my.application.routes`. +# Default to Routes in the root package (and `conf/routes`) +# application.router=my.application.Routes + +# Database configuration +# ~~~~~ +# You can declare as many datasources as you want. +# By convention, the default datasource is named `default` +# +# db.default.driver=org.h2.Driver +# db.default.url="jdbc:h2:mem:play" +# db.default.user=sa +# db.default.password="" +# +# You can expose this datasource via JNDI if needed (Useful for JPA) +# db.default.jndiName=DefaultDS + +db.default.driver= com.mysql.jdbc.Driver +db.default.url="jdbc:mysql://127.0.0.1:3306/hello_world?jdbcCompliantTruncation=false&elideSetAutoCommits=true&useLocalSessionState=true&cachePrepStmts=true&cacheCallableStmts=true&alwaysSendSetIsolation=false&prepStmtCacheSize=4096&cacheServerConfiguration=true&prepStmtCacheSqlLimit=2048&zeroDateTimeBehavior=convertToNull&traceProtocol=false&useUnbufferedInput=false&useReadAheadInput=false&maintainTimeStats=false&useServerPrepStmts&cacheRSMetadata=true" +db.default.user=benchmarkdbuser +db.default.password=benchmarkdbpass +db.default.jndiName=DefaultDS +jpa.default=defaultPersistenceUnit + +db.default.partitionCount=4 + +# The number of connections to create per partition. Setting this to +# 5 with 3 partitions means you will have 15 unique connections to the +# database. Note that BoneCP will not create all these connections in +# one go but rather start off with minConnectionsPerPartition and +# gradually increase connections as required. +# +# This value maps to the maximumPoolSize for HickariCP (db.default.partitionCount * db.default.maxConnectionsPerPartition) +db.default.maxConnectionsPerPartition=64 + +# The number of initial connections, per partition. +# +# This maps to the minimumIdle connections for HikariCP (db.default.partitionCount * db.default.minConnectionsPerPartition) +db.default.minConnectionsPerPartition=64 + +dbplugin=disabled + +# Evolutions +# ~~~~~ +# You can disable evolutions if needed +evolutionplugin=disabled + +# Ebean configuration +# ~~~~~ +# You can declare as many Ebean servers as you want. +# By convention, the default server is named `default` +# +# ebean.default="models.*" + +# Logger +# ~~~~~ +# You can also configure logback (http://logback.qos.ch/), +# by providing an application-logger.xml file in the conf directory. + +# Root logger: +logger.root=ERROR + +# Logger used by the framework: +logger.play=INFO + +# Logger provided to your application: +logger.application=DEBUG + diff --git a/frameworks/Java/play2-java/play2-java-jpa-hikaricp/conf/play.plugins b/frameworks/Java/play2-java/play2-java-jpa-hikaricp/conf/play.plugins new file mode 100644 index 00000000000..d2a9a6e0be1 --- /dev/null +++ b/frameworks/Java/play2-java/play2-java-jpa-hikaricp/conf/play.plugins @@ -0,0 +1 @@ +200:com.edulify.play.hikaricp.HikariCPPlugin \ No newline at end of file diff --git a/frameworks/Java/play2-java/play2-java-jpa-hikaricp/conf/routes b/frameworks/Java/play2-java/play2-java-jpa-hikaricp/conf/routes new file mode 100644 index 00000000000..caa32579461 --- /dev/null +++ b/frameworks/Java/play2-java/play2-java-jpa-hikaricp/conf/routes @@ -0,0 +1,13 @@ +# Routes +# This file defines all application routes (Higher priority routes first) +# ~~~~ + +GET /json controllers.Application.json +GET /db controllers.Application.db() +GET /queries controllers.Application.queries(queries ?= "1") +GET /fortunes controllers.Application.fortunes +GET /update controllers.Application.update(queries ?= "1") +GET /plaintext controllers.Application.plainText + +# Map static resources from the /public folder to the /assets URL path +GET /assets/*file controllers.Assets.at(path="/public", file) diff --git a/frameworks/Java/play2-java/play2-java-jpa-hikaricp/project/build.properties b/frameworks/Java/play2-java/play2-java-jpa-hikaricp/project/build.properties new file mode 100644 index 00000000000..be6c454fbac --- /dev/null +++ b/frameworks/Java/play2-java/play2-java-jpa-hikaricp/project/build.properties @@ -0,0 +1 @@ +sbt.version=0.13.5 diff --git a/frameworks/Java/play2-java/play2-java-jpa-hikaricp/project/plugins.sbt b/frameworks/Java/play2-java/play2-java-jpa-hikaricp/project/plugins.sbt new file mode 100644 index 00000000000..15733761d7d --- /dev/null +++ b/frameworks/Java/play2-java/play2-java-jpa-hikaricp/project/plugins.sbt @@ -0,0 +1,4 @@ +resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/" + +// The Play plugin +addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.6") \ No newline at end of file diff --git a/frameworks/Java/play2-java/play2-java-jpa-hikaricp/source_code b/frameworks/Java/play2-java/play2-java-jpa-hikaricp/source_code new file mode 100644 index 00000000000..3bc487b4d68 --- /dev/null +++ b/frameworks/Java/play2-java/play2-java-jpa-hikaricp/source_code @@ -0,0 +1,11 @@ +./play-java-jpa/app/ +./play-java-jpa/app/controllers +./play-java-jpa/app/controllers/Application.java +./play-java-jpa/app/utils +./play-java-jpa/app/utils/Headers.java +./play-java-jpa/app/utils/Predicate.java +./play-java-jpa/app/utils/PredicatedAction.java +./play-java-jpa/app/utils/Predicated.java +./play-java-jpa/app/models +./play-java-jpa/app/models/World.java +./play-java-jpa/app/models/Fortune.java diff --git a/frameworks/Java/play2-java/play2-java-jpa/README.md b/frameworks/Java/play2-java/play2-java-jpa/README.md index 1d2b8844f4b..c210444400e 100644 --- a/frameworks/Java/play2-java/play2-java-jpa/README.md +++ b/frameworks/Java/play2-java/play2-java-jpa/README.md @@ -4,25 +4,37 @@ This is the Play portion of a [benchmarking test suite](../) comparing a variety ### JSON Encoding Test -* [JSON test source](app/controllers/Application.java) +* [JSON test controller](app/controllers/Application.java) ### Data-Store/Database Mapping Test * [Database test controller](app/controllers/Application.java) -* [Database test model](app/models/World.java) +* [Database World test model](app/models/World.java) +* [Database Fortune test model](app/models/Fortune.java) + +### Plain Text Test + +* [Plain text test controller](app/controllers/Application.java) ## Infrastructure Software Versions The tests were run with: * [Java OpenJDK 1.7](http://openjdk.java.net/) -* [Play 2.3.3](http://http://www.playframework.com/) +* [Play 2.3.6](http://http://www.playframework.com/) ## Test URLs ### JSON Encoding Test -http://localhost/json +* http://localhost/json ### Data-Store/Database Mapping Test -http://localhost/db -http://localhost/queries?queries=10 \ No newline at end of file +* http://localhost/db +* http://localhost/queries?queries=10 +* http://localhost/fortunes +* http://localhost/update?queries=10 + +### Plain Text Test + +* http://localhost/plaintext + diff --git a/frameworks/Java/play2-java/play2-java-jpa/app/controllers/Application.java b/frameworks/Java/play2-java/play2-java-jpa/app/controllers/Application.java index 5114ee6e409..c9290d78d5d 100644 --- a/frameworks/Java/play2-java/play2-java-jpa/app/controllers/Application.java +++ b/frameworks/Java/play2-java/play2-java-jpa/app/controllers/Application.java @@ -3,6 +3,7 @@ import akka.dispatch.ExecutionContexts; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; +import models.Fortune; import models.World; import play.Play; import play.core.NamedThreadFactory; @@ -14,9 +15,7 @@ import utils.Predicate; import utils.Predicated; -import java.util.ArrayList; -import java.util.List; -import java.util.Random; +import java.util.*; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.ThreadPoolExecutor; @@ -24,7 +23,6 @@ public class Application extends Controller { - private static final int MAX_QUERIES_PER_REQUEST = 20; private static final int TEST_DATABASE_ROWS = 10000; private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); @@ -69,6 +67,54 @@ public Result apply(List worlds) { @Predicated(predicate = IsDbAvailable.class, failed = SERVICE_UNAVAILABLE) public static F.Promise queries(final String queryCountString) { + return getRandomWorlds(queryCount(queryCountString)).map(new F.Function, Result>() { + @Override + public Result apply(List worlds) { + return ok(Json.toJson(worlds)); + } + }); + } + + @Predicated(predicate = IsDbAvailable.class, failed = SERVICE_UNAVAILABLE) + public static F.Promise fortunes() { + return F.Promise.promise(new F.Function0() { + + @Override + public Result apply() throws Throwable { + List fortunes = Fortune.findAll(); + fortunes.add(new Fortune("Additional fortune added at request time.")); + Collections.sort(fortunes, new Comparator() { + @Override + public int compare(Fortune f1, Fortune f2) { + return f1.message.compareTo(f2.message); + } + }); + return ok(views.html.fortunes.render(fortunes)); + } + }, dbEc); + } + + @Predicated(predicate = IsDbAvailable.class, failed = SERVICE_UNAVAILABLE) + public static F.Promise update(final String queryCountString) { + return getRandomWorlds(queryCount(queryCountString)).map(new F.Function, Result>() { + @Override + public Result apply(List worlds) throws Throwable { + Random random = ThreadLocalRandom.current(); + for (World world : worlds) { + world.randomNumber = (long) (random.nextInt(10000) + 1); + } + + worlds = World.save(worlds); + return ok(Json.toJson(worlds)); + } + }); + } + + public static Result plainText() { + return ok("Hello, World!"); + } + + private static int queryCount(String queryCountString) { int queryCount; try { queryCount = Integer.parseInt(queryCountString, 10); @@ -81,12 +127,7 @@ public static F.Promise queries(final String queryCountString) { queryCount = 500; } - return getRandomWorlds(queryCount).map(new F.Function, Result>() { - @Override - public Result apply(List worlds) { - return ok(Json.toJson(worlds)); - } - }); + return queryCount; } private static F.Promise> getRandomWorlds(final int n) { diff --git a/frameworks/Java/play2-java/play2-java-jpa/app/models/Fortune.java b/frameworks/Java/play2-java/play2-java-jpa/app/models/Fortune.java new file mode 100644 index 00000000000..5d549b33a59 --- /dev/null +++ b/frameworks/Java/play2-java/play2-java-jpa/app/models/Fortune.java @@ -0,0 +1,34 @@ +package models; + +import play.db.jpa.JPA; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.criteria.CriteriaQuery; +import java.util.List; + +@Entity +public class Fortune { + + @Id + public Long id = 0L; + + public String message; + + public Fortune() { + } + + public Fortune(String message) { + this.message = message; + } + + public static List findAll() throws Throwable { + return JPA.withTransaction("default", true, new play.libs.F.Function0>() { + public List apply() { + CriteriaQuery criteria = JPA.em().getCriteriaBuilder().createQuery(Fortune.class); + criteria.select(criteria.from(Fortune.class)); + return JPA.em().createQuery(criteria).getResultList(); + } + }); + } +} \ No newline at end of file diff --git a/frameworks/Java/play2-java/play2-java-jpa/app/models/World.java b/frameworks/Java/play2-java/play2-java-jpa/app/models/World.java index 71cf10786f3..1382664f9c2 100644 --- a/frameworks/Java/play2-java/play2-java-jpa/app/models/World.java +++ b/frameworks/Java/play2-java/play2-java-jpa/app/models/World.java @@ -1,9 +1,12 @@ package models; -import javax.persistence.*; - import play.db.jpa.JPA; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import java.util.List; + @Entity public class World { @@ -14,10 +17,22 @@ public class World { public Long randomNumber; public static World findById(final Long id) throws Throwable { - return JPA.withTransaction("default", true, new play.libs.F.Function0() { - public World apply() { - return JPA.em().find(World.class, id); + return JPA.withTransaction("default", true, new play.libs.F.Function0() { + public World apply() { + return JPA.em().find(World.class, id); + } + }); + } + + public static List save(final List worlds) throws Throwable { + for (final World world : worlds) { + JPA.withTransaction("default", false, new play.libs.F.Function0() { + public World apply() { + return JPA.em().merge(world); + } + }); } - }); + + return worlds; } } \ No newline at end of file diff --git a/frameworks/Java/play2-java/play2-java-jpa/app/utils/Headers.java b/frameworks/Java/play2-java/play2-java-jpa/app/utils/Headers.java new file mode 100644 index 00000000000..253c4aa70d2 --- /dev/null +++ b/frameworks/Java/play2-java/play2-java-jpa/app/utils/Headers.java @@ -0,0 +1,21 @@ +package utils; + +import org.joda.time.DateTime; +import org.joda.time.format.DateTimeFormat; +import org.joda.time.format.DateTimeFormatter; +import play.libs.F; +import play.mvc.Action; +import play.mvc.Http; +import play.mvc.Result; + +public class Headers extends Action.Simple { + + private static final DateTimeFormatter RFC_1123_DATE_TIME = DateTimeFormat.forPattern("EEE, dd MMM yyyy HH:mm:ss 'GMT'").withZoneUTC(); + + @Override + public F.Promise call(Http.Context context) throws Throwable { + context.response().setHeader("Server", "play2-java-jpa"); + context.response().setHeader("Date", RFC_1123_DATE_TIME.print(new DateTime())); + return delegate.call(context); + } +} diff --git a/frameworks/Java/play2-java/play2-java-jpa/app/views/fortunes.scala.html b/frameworks/Java/play2-java/play2-java-jpa/app/views/fortunes.scala.html new file mode 100644 index 00000000000..57a634ef90a --- /dev/null +++ b/frameworks/Java/play2-java/play2-java-jpa/app/views/fortunes.scala.html @@ -0,0 +1,16 @@ +@(fortunes: List[Fortune]) + +@main() { + + + + + + @for(fortune <- fortunes) { + + + + + } +
idmessage
@fortune.id@fortune.message
+} \ No newline at end of file diff --git a/frameworks/Java/play2-java/play2-java-jpa/app/views/main.scala.html b/frameworks/Java/play2-java/play2-java-jpa/app/views/main.scala.html new file mode 100644 index 00000000000..ede13a1641b --- /dev/null +++ b/frameworks/Java/play2-java/play2-java-jpa/app/views/main.scala.html @@ -0,0 +1,12 @@ +@()(content: Html) + + + + + + Fortunes + + + @content + + \ No newline at end of file diff --git a/frameworks/Java/play2-java/play2-java-jpa/build.sbt b/frameworks/Java/play2-java/play2-java-jpa/build.sbt index 4e44edaf835..58361469cdc 100644 --- a/frameworks/Java/play2-java/play2-java-jpa/build.sbt +++ b/frameworks/Java/play2-java/play2-java-jpa/build.sbt @@ -9,7 +9,7 @@ lazy val root = (project in file(".")).enablePlugins(PlayJava) libraryDependencies ++= Seq( javaJdbc, javaJpa, - "mysql" % "mysql-connector-java" % "5.1.32", + "mysql" % "mysql-connector-java" % "5.1.33", "org.hibernate" % "hibernate-entitymanager" % "4.3.6.Final" ) diff --git a/frameworks/Java/play2-java/play2-java-jpa/conf/routes b/frameworks/Java/play2-java/play2-java-jpa/conf/routes index 88c0c8055a9..caa32579461 100644 --- a/frameworks/Java/play2-java/play2-java-jpa/conf/routes +++ b/frameworks/Java/play2-java/play2-java-jpa/conf/routes @@ -2,10 +2,12 @@ # This file defines all application routes (Higher priority routes first) # ~~~~ -# Home page GET /json controllers.Application.json GET /db controllers.Application.db() GET /queries controllers.Application.queries(queries ?= "1") +GET /fortunes controllers.Application.fortunes +GET /update controllers.Application.update(queries ?= "1") +GET /plaintext controllers.Application.plainText # Map static resources from the /public folder to the /assets URL path GET /assets/*file controllers.Assets.at(path="/public", file) diff --git a/frameworks/Java/play2-java/play2-java-jpa/project/plugins.sbt b/frameworks/Java/play2-java/play2-java-jpa/project/plugins.sbt index 8237e937e74..2dbb2304409 100644 --- a/frameworks/Java/play2-java/play2-java-jpa/project/plugins.sbt +++ b/frameworks/Java/play2-java/play2-java-jpa/project/plugins.sbt @@ -5,4 +5,4 @@ logLevel := Level.Warn resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/" // Use the Play sbt plugin for Play projects -addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.4") +addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.6") diff --git a/frameworks/Java/play2-java/play2-java-jpa/source_code b/frameworks/Java/play2-java/play2-java-jpa/source_code index 453f91c91ec..3bc487b4d68 100644 --- a/frameworks/Java/play2-java/play2-java-jpa/source_code +++ b/frameworks/Java/play2-java/play2-java-jpa/source_code @@ -2,8 +2,10 @@ ./play-java-jpa/app/controllers ./play-java-jpa/app/controllers/Application.java ./play-java-jpa/app/utils +./play-java-jpa/app/utils/Headers.java ./play-java-jpa/app/utils/Predicate.java ./play-java-jpa/app/utils/PredicatedAction.java ./play-java-jpa/app/utils/Predicated.java ./play-java-jpa/app/models ./play-java-jpa/app/models/World.java +./play-java-jpa/app/models/Fortune.java diff --git a/frameworks/Java/play2-java/setup_java_jpa_hikaricp.py b/frameworks/Java/play2-java/setup_java_jpa_hikaricp.py new file mode 100644 index 00000000000..342b68cfc28 --- /dev/null +++ b/frameworks/Java/play2-java/setup_java_jpa_hikaricp.py @@ -0,0 +1,6 @@ + +# This file was generated by frameworks/Java/play2-java/generate_config.py. +# Do not edit this file directly, use the script to regenerate. +from .setup_common import make_setup_for_dir + +make_setup_for_dir(globals(), 'play2-java-jpa-hikaricp')