Browse Source

jooby 2.0.0.M2 (#4607)

- upgrade to latest jooby
Edgar Espina 6 years ago
parent
commit
2daabb4a08

+ 3 - 0
frameworks/Java/jooby2/conf/application.conf

@@ -0,0 +1,3 @@
+db.url = "jdbc:postgresql://tfb-database:5432/hello_world"
+db.user = benchmarkdbuser
+db.password = benchmarkdbpass

+ 0 - 4
frameworks/Java/jooby2/conf/application.properties

@@ -1,4 +0,0 @@
-
-db.url = jdbc:postgresql://tfb-database:5432/hello_world
-db.user = benchmarkdbuser
-db.password = benchmarkdbpass

+ 10 - 10
frameworks/Java/jooby2/pom.xml

@@ -7,7 +7,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>jooby-project</artifactId>
-    <version>2.0.0.M1</version>
+    <version>2.0.0.M2</version>
   </parent>
 
   <artifactId>jooby2</artifactId>
@@ -17,8 +17,8 @@
   <name>jooby 2.x</name>
 
   <properties>
-    <jooby.version>2.0.0.M1</jooby.version>
-    <postgresql.version>42.2.2</postgresql.version>
+    <jooby.version>2.0.0.M2</jooby.version>
+    <postgresql.version>42.2.5</postgresql.version>
 
     <!-- Startup class -->
     <application.class>com.techempower.App</application.class>
@@ -37,6 +37,12 @@
       <artifactId>jooby-hikari</artifactId>
     </dependency>
 
+    <!-- rocker -->
+    <dependency>
+      <groupId>io.jooby</groupId>
+      <artifactId>jooby-rocker</artifactId>
+    </dependency>
+
     <!-- mySQL -->
     <dependency>
       <groupId>mysql</groupId>
@@ -50,13 +56,6 @@
       <version>${postgresql.version}</version>
     </dependency>
 
-    <!-- rocker -->
-    <dependency>
-      <groupId>com.fizzed</groupId>
-      <artifactId>rocker-runtime</artifactId>
-      <version>1.2.1</version>
-    </dependency>
-
     <!-- logging -->
     <dependency>
       <groupId>ch.qos.logback</groupId>
@@ -81,6 +80,7 @@
             <configuration>
               <templateDirectory>public</templateDirectory>
               <touchFile>/dev/null</touchFile>
+              <optimize>true</optimize>
             </configuration>
           </execution>
         </executions>

+ 83 - 80
frameworks/Java/jooby2/src/main/java/com/techempower/App.java

@@ -1,51 +1,56 @@
 package com.techempower;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fizzed.rocker.runtime.ArrayOfByteArraysOutput;
 import com.zaxxer.hikari.HikariConfig;
 import com.zaxxer.hikari.HikariDataSource;
 import io.jooby.Context;
 import io.jooby.Env;
 import io.jooby.Jooby;
+import io.jooby.ServerOptions;
 import io.jooby.hikari.Hikari;
 import io.jooby.json.Jackson;
+import io.jooby.rocker.Rockerby;
 
-import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
 import java.sql.Connection;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
-import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Random;
+import java.util.StringJoiner;
 import java.util.concurrent.ThreadLocalRandom;
 
 import javax.sql.DataSource;
 
 import static io.jooby.ExecutionMode.EVENT_LOOP;
-import static io.jooby.MediaType.html;
-import static io.jooby.MediaType.json;
-import static java.sql.ResultSet.CONCUR_READ_ONLY;
-import static java.sql.ResultSet.TYPE_FORWARD_ONLY;
+import static io.jooby.MediaType.JSON;
 
 public class App extends Jooby {
 
-  private static final String UPDATE_WORLD = "update world set randomNumber=? where id=?";
-
   private static final String SELECT_WORLD = "select * from world where id=?";
 
   private static final int DB_ROWS = 10000;
 
-  private static final String HELLO_WORLD = "Hello, World!";
+  private static final String MESSAGE = "Hello, World!";
+
+  private static final ByteBuffer MESSAGE_BUFFER = (ByteBuffer) ByteBuffer
+      .allocateDirect(MESSAGE.length())
+      .put(MESSAGE.getBytes(StandardCharsets.US_ASCII))
+      .flip();
 
   public static class Message {
-    public final String message = HELLO_WORLD;
+    public final String message = MESSAGE;
   }
 
   {
     Env env = Env.defaultEnvironment(getClass().getClassLoader());
 
+    /** Server options (netty only): */
+    setServerOptions(new ServerOptions().setSingleLoop(true));
+
     /** JSON: */
     ObjectMapper mapper = Jackson.defaultObjectMapper();
 
@@ -53,12 +58,15 @@ public class App extends Jooby {
     HikariConfig conf = new Hikari.Builder().build(env);
     DataSource ds = new HikariDataSource(conf);
 
+    /** Template engine: */
+    install(new Rockerby());
+
     get("/plaintext", ctx ->
-        ctx.sendString(HELLO_WORLD)
+        ctx.sendBytes(MESSAGE_BUFFER.duplicate())
     );
 
     get("/json", ctx -> ctx
-        .setContentType(json)
+        .setContentType(JSON)
         .sendBytes(mapper.writeValueAsBytes(new Message()))
     );
 
@@ -66,57 +74,79 @@ public class App extends Jooby {
     dispatch(() -> {
 
       /** Single query: */
-      get("/db", ctx -> ctx
-          .setContentType(json)
-          .sendBytes(mapper.writeValueAsBytes(findOne(ds, rndId(ThreadLocalRandom.current()))))
-      );
+      get("/db", ctx -> {
+        Random rnd = ThreadLocalRandom.current();
+        World result;
+        try (Connection conn = ds.getConnection()) {
+          int id = nextRandom(rnd);
+          try (final PreparedStatement statement = conn.prepareStatement(SELECT_WORLD)) {
+            statement.setInt(1, id);
+            try (ResultSet rs = statement.executeQuery()) {
+              rs.next();
+              result = new World(rs.getInt("id"), rs.getInt("randomNumber"));
+            }
+          }
+        }
+        return ctx
+            .setContentType(JSON)
+            .sendBytes(mapper.writeValueAsBytes(result));
+      });
 
       /** Multiple queries: */
       get("/queries", ctx -> {
-        // bound count
-        int count = queries(ctx);
-        List<World> result = new ArrayList<>();
+        World[] result = new World[queries(ctx)];
         Random rnd = ThreadLocalRandom.current();
         try (Connection conn = ds.getConnection()) {
-          for (int i = 0; i < count; i++) {
-            int id = rndId(rnd);
-            try (final PreparedStatement query = conn
-                .prepareStatement(SELECT_WORLD, TYPE_FORWARD_ONLY,
-                    CONCUR_READ_ONLY)) {
-              result.add(findOne(query, id));
+          for (int i = 0; i < result.length; i++) {
+            int id = nextRandom(rnd);
+            try (final PreparedStatement statement = conn.prepareStatement(SELECT_WORLD)) {
+              statement.setInt(1, id);
+              try (ResultSet rs = statement.executeQuery()) {
+                rs.next();
+                result[i] = new World(rs.getInt("id"), rs.getInt("randomNumber"));
+              }
             }
           }
         }
-        ctx.setContentType(json);
-        return ctx.sendBytes(mapper.writeValueAsBytes(result));
+        return ctx
+            .setContentType(JSON)
+            .sendBytes(mapper.writeValueAsBytes(result));
       });
 
       /** Updates: */
       get("/updates", ctx -> {
-        // bound count
-        int count = queries(ctx);
-        List<World> result = new ArrayList<>();
+        World[] result = new World[queries(ctx)];
         Random rnd = ThreadLocalRandom.current();
-        try (Connection conn = ds.getConnection()) {
-          for (int i = 0; i < count; i++) {
-            int id = rndId(rnd);
-            int newRandomNumber = rndId(rnd);
-            try (final PreparedStatement query = conn
-                .prepareStatement(SELECT_WORLD, TYPE_FORWARD_ONLY, CONCUR_READ_ONLY);
-                final PreparedStatement update = conn.prepareStatement(UPDATE_WORLD)) {
-              // find
-              World world = findOne(query, id);
-
-              // update
-              update.setInt(1, newRandomNumber);
-              update.setInt(2, id);
-              update.execute();
-
-              result.add(new World(world.id, newRandomNumber));
+
+        StringJoiner updateSql = new StringJoiner(
+            ", ",
+            "UPDATE world SET randomNumber = temp.randomNumber FROM (VALUES ",
+            " ORDER BY 1) AS temp(id, randomNumber) WHERE temp.id = world.id");
+
+        try (Connection connection = ds.getConnection()) {
+          try (PreparedStatement statement = connection.prepareStatement(SELECT_WORLD)) {
+            for (int i = 0; i < result.length; i++) {
+              statement.setInt(1, nextRandom(rnd));
+              try (ResultSet rs = statement.executeQuery()) {
+                rs.next();
+                result[i] = new World(rs.getInt("id"), rs.getInt("randomNumber"));
+              }
+              // prepare update query
+              updateSql.add("(?, ?)");
             }
           }
+
+          try (PreparedStatement statement = connection.prepareStatement(updateSql.toString())) {
+            int i = 0;
+            for (World world : result) {
+              world.randomNumber = nextRandom(rnd);
+              statement.setInt(++i, world.id);
+              statement.setInt(++i, world.randomNumber);
+            }
+            statement.executeUpdate();
+          }
         }
-        ctx.setContentType(json);
+        ctx.setContentType(JSON);
         return ctx.sendBytes(mapper.writeValueAsBytes(result));
       });
 
@@ -124,8 +154,7 @@ public class App extends Jooby {
       get("/fortunes", ctx -> {
         List<Fortune> fortunes = new ArrayList<>();
         try (Connection connection = ds.getConnection()) {
-          try (PreparedStatement stt = connection
-              .prepareStatement("select * from fortune", TYPE_FORWARD_ONLY, CONCUR_READ_ONLY)) {
+          try (PreparedStatement stt = connection.prepareStatement("select * from fortune")) {
             try (ResultSet rs = stt.executeQuery()) {
               while (rs.next()) {
                 fortunes.add(new Fortune(rs.getInt("id"), rs.getString("message")));
@@ -137,46 +166,20 @@ public class App extends Jooby {
         Collections.sort(fortunes);
 
         /** render view: */
-        views.fortunes template = views.fortunes.template(fortunes);
-        ArrayOfByteArraysOutput buff = template.render(ArrayOfByteArraysOutput.FACTORY);
-        ctx.setContentLength(buff.getByteLength());
-        try (OutputStream output = ctx.responseStream(html)) {
-          for (byte[] chunk : buff.getArrays()) {
-            output.write(chunk);
-          }
-        }
-        return ctx;
+        return views.fortunes.template(fortunes);
       });
     });
   }
 
   public static void main(final String[] args) {
-    run(App::new, EVENT_LOOP, args);
-  }
-
-  private World findOne(DataSource ds, int id) throws SQLException {
-    try (Connection conn = ds.getConnection()) {
-      try (PreparedStatement query = conn
-          .prepareStatement(SELECT_WORLD, TYPE_FORWARD_ONLY,
-              CONCUR_READ_ONLY)) {
-        return findOne(query, id);
-      }
-    }
-  }
-
-  private World findOne(PreparedStatement query, int id) throws SQLException {
-    query.setInt(1, id);
-    try (ResultSet resultSet = query.executeQuery()) {
-      resultSet.next();
-      return new World(resultSet.getInt("id"), resultSet.getInt("randomNumber"));
-    }
+    runApp(EVENT_LOOP, args, App::new);
   }
 
-  private final int rndId(Random rnd) {
+  private final int nextRandom(Random rnd) {
     return rnd.nextInt(DB_ROWS) + 1;
   }
 
-  private int   queries(Context ctx) {
+  private int queries(Context ctx) {
     String value = ctx.query("queries").value("");
     if (value.length() == 0) {
       return 1;

+ 2 - 2
frameworks/Java/jooby2/src/main/java/com/techempower/World.java

@@ -2,8 +2,8 @@ package com.techempower;
 
 public class World {
 
-  public final int id;
-  public final int randomNumber;
+  public int id;
+  public int randomNumber;
 
   public World(int id, int randomNumber) {
     this.id = id;