Browse Source

Upgrade deps, tune perf, add undertow servlet and undertow webactors conf

circlespainter 9 years ago
parent
commit
fb9c8c7e8b
37 changed files with 542 additions and 291 deletions
  1. 2 0
      frameworks/Java/comsat-servlet/.gitignore
  2. 5 4
      frameworks/Java/comsat-servlet/README.md
  3. 20 1
      frameworks/Java/comsat-servlet/benchmark_config.json
  4. 36 7
      frameworks/Java/comsat-servlet/build.gradle
  5. BIN
      frameworks/Java/comsat-servlet/gradle/wrapper/gradle-wrapper.jar
  6. 2 2
      frameworks/Java/comsat-servlet/gradle/wrapper/gradle-wrapper.properties
  7. 25 21
      frameworks/Java/comsat-servlet/gradlew
  8. 3 3
      frameworks/Java/comsat-servlet/gradlew.bat
  9. 8 0
      frameworks/Java/comsat-servlet/setup-generic.sh
  10. 5 0
      frameworks/Java/comsat-servlet/setup-jetty.sh
  11. 5 0
      frameworks/Java/comsat-servlet/setup-undertow.sh
  12. 2 7
      frameworks/Java/comsat-servlet/setup.sh
  13. 7 2
      frameworks/Java/comsat-servlet/source_code
  14. 44 0
      frameworks/Java/comsat-servlet/src/main/java/hello/JettyServer.java
  15. 27 0
      frameworks/Java/comsat-servlet/src/main/java/hello/JsonServlet.java
  16. 22 0
      frameworks/Java/comsat-servlet/src/main/java/hello/PlaintextServlet.java
  17. 6 0
      frameworks/Java/comsat-servlet/src/main/java/hello/Server.java
  18. 9 40
      frameworks/Java/comsat-servlet/src/main/java/hello/UndertowServer.java
  19. 10 0
      frameworks/Java/comsat-servlet/src/main/java/hello/World.java
  20. 3 2
      frameworks/Java/comsat-webactors/README.md
  21. 20 1
      frameworks/Java/comsat-webactors/benchmark_config.json
  22. 31 7
      frameworks/Java/comsat-webactors/build.gradle
  23. BIN
      frameworks/Java/comsat-webactors/gradle/wrapper/gradle-wrapper.jar
  24. 2 2
      frameworks/Java/comsat-webactors/gradle/wrapper/gradle-wrapper.properties
  25. 25 21
      frameworks/Java/comsat-webactors/gradlew
  26. 3 3
      frameworks/Java/comsat-webactors/gradlew.bat
  27. 8 0
      frameworks/Java/comsat-webactors/setup-generic.sh
  28. 5 0
      frameworks/Java/comsat-webactors/setup-netty.sh
  29. 5 0
      frameworks/Java/comsat-webactors/setup-undertow.sh
  30. 2 8
      frameworks/Java/comsat-webactors/setup.sh
  31. 5 1
      frameworks/Java/comsat-webactors/source_code
  32. 0 159
      frameworks/Java/comsat-webactors/src/main/java/hello/HelloWebActor.java
  33. 67 0
      frameworks/Java/comsat-webactors/src/main/java/hello/NettyServer.java
  34. 6 0
      frameworks/Java/comsat-webactors/src/main/java/hello/Server.java
  35. 55 0
      frameworks/Java/comsat-webactors/src/main/java/hello/UndertowServer.java
  36. 57 0
      frameworks/Java/comsat-webactors/src/main/java/hello/WebActor.java
  37. 10 0
      frameworks/Java/comsat-webactors/src/main/java/hello/World.java

+ 2 - 0
frameworks/Java/comsat-servlet/.gitignore

@@ -2,3 +2,5 @@
 build/
 gradle-app.setting
 !gradle-wrapper.jar
+.idea
+*.iml

+ 5 - 4
frameworks/Java/comsat-servlet/README.md

@@ -9,10 +9,11 @@ This is the [Parallel Universe Comsat Servlet](http://docs.paralleluniverse.co/c
 
 ## Versions
 
-* Jackson JSON 2.7.0 (https://github.com/FasterXML/jackson)
-* Quasar 0.7.4 (http://docs.paralleluniverse.co/quasar)
-* Comsat 0.6.0-SNAPSHOT (http://docs.paralleluniverse.co/comsat)
-* Undertow 1.3.15-final (http://undertow.io)
+* Jackson JSON 2.7.4 (https://github.com/FasterXML/jackson)
+* Quasar 0.7.5 (http://docs.paralleluniverse.co/quasar)
+* Comsat 0.7.0 (http://docs.paralleluniverse.co/comsat)
+* Jetty 9.3.9.v20160517 (https://www.eclipse.org/jetty/)
+* Undertow 1.3.22-final (http://undertow.io)
 
 ## Test URLs
 

+ 20 - 1
frameworks/Java/comsat-servlet/benchmark_config.json

@@ -3,7 +3,26 @@
   "tests": [
     {
       "default": {
-        "setup_file": "setup",
+        "setup_file": "setup-jetty",
+        "json_url": "/json",
+        "plaintext_url": "/plaintext",
+        "port": 8080,
+        "approach": "Realistic",
+        "classification": "Platform",
+        "database": "None",
+        "framework": "comsat-servlet",
+        "language": "Java",
+        "orm": "Raw",
+        "platform": "Comsat Servlet",
+        "webserver": "Jetty",
+        "os": "Linux",
+        "database_os": "Linux",
+        "display_name": "comsat-servlet-jetty",
+        "notes": "Comsat servlet on embedded Jetty",
+        "versus": ""
+      },
+      "undertow": {
+        "setup_file": "setup-undertow",
         "json_url": "/json",
         "plaintext_url": "/plaintext",
         "port": 8080,

+ 36 - 7
frameworks/Java/comsat-servlet/build.gradle

@@ -8,12 +8,15 @@ apply plugin: 'java'
 sourceCompatibility = 1.8
 targetCompatibility = 1.8
 
-version = '0.2'
+version = '0.3'
 
-ext.jacksonVer = '2.7.0'
-ext.quasarVer  = '0.7.4'
-ext.comsatVer  = '0.6.0'
-ext.capsuleVer = '1.0.1'
+ext.jacksonVer  = '2.7.4'
+ext.quasarVer   = '0.7.5'
+ext.comsatVer   = '0.7.0'
+ext.capsuleVer  = '1.0.2'
+
+ext.jettyVer    = '9.3.9.v20160517'
+ext.undertowVer = '1.3.22.Final'
 
 [compileJava, compileTestJava]*.options*.encoding = "UTF-8"
 
@@ -27,6 +30,24 @@ configurations {
     quasar
 }
 
+configurations.all {
+    resolutionStrategy {
+        failOnVersionConflict()
+        force "org.eclipse.jetty:jetty-util:$jettyVer"
+        force "org.eclipse.jetty:jetty-io:$jettyVer"
+        force "org.eclipse.jetty:jetty-http:$jettyVer"
+        force "org.eclipse.jetty:jetty-server:$jettyVer"
+        force "org.eclipse.jetty:jetty-servlet:$jettyVer"
+        force "org.eclipse.jetty:jetty-webapp:$jettyVer"
+        force "org.eclipse.jetty:jetty-xml:$jettyVer"
+        force "org.eclipse.jetty.websocket:websocket-server:$jettyVer"
+        force "org.eclipse.jetty.websocket:websocket-servlet:$jettyVer"
+        force "org.eclipse.jetty.websocket:websocket-client:$jettyVer"
+        force "io.undertow:undertow-core:$undertowVer"
+        force "io.undertow:undertow-servlet:$undertowVer"
+    }
+}
+
 configurations.capsule.dependencies.clear()
 
 dependencies {
@@ -41,13 +62,21 @@ dependencies {
 }
 
 task capsule(type: FatCapsule) {
-    applicationClass "hello.HelloWebServer"
+    applicationClass "hello.World"
 
     capsuleManifest {
         javaAgents = [configurations.quasar.iterator().next().getName()]
+
+        mode('undertow') {
+            systemProperties['serverClass'] = 'hello.UndertowServer'
+        }
+
+        mode('jetty') {
+            systemProperties['serverClass'] = 'hello.JettyServer'
+        }
     }
 }
 
 task wrapper(type: Wrapper) {
-    gradleVersion = '2.11'
+    gradleVersion = '2.14'
 }

BIN
frameworks/Java/comsat-servlet/gradle/wrapper/gradle-wrapper.jar


+ 2 - 2
frameworks/Java/comsat-servlet/gradle/wrapper/gradle-wrapper.properties

@@ -1,6 +1,6 @@
-#Tue Feb 09 19:18:32 IST 2016
+#Wed Jun 15 10:16:02 IDT 2016
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-2.11-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.14-bin.zip

+ 25 - 21
frameworks/Java/comsat-servlet/gradlew

@@ -6,12 +6,30 @@
 ##
 ##############################################################################
 
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS=""
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
 
 APP_NAME="Gradle"
 APP_BASE_NAME=`basename "$0"`
 
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
 # Use the maximum available, or set MAX_FD != -1 to use that value.
 MAX_FD="maximum"
 
@@ -30,6 +48,7 @@ die ( ) {
 cygwin=false
 msys=false
 darwin=false
+nonstop=false
 case "`uname`" in
   CYGWIN* )
     cygwin=true
@@ -40,26 +59,11 @@ case "`uname`" in
   MINGW* )
     msys=true
     ;;
+  NONSTOP* )
+    nonstop=true
+    ;;
 esac
 
-# Attempt to set APP_HOME
-# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
-    ls=`ls -ld "$PRG"`
-    link=`expr "$ls" : '.*-> \(.*\)$'`
-    if expr "$link" : '/.*' > /dev/null; then
-        PRG="$link"
-    else
-        PRG=`dirname "$PRG"`"/$link"
-    fi
-done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
-APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
-
 CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
 
 # Determine the Java command to use to start the JVM.
@@ -85,7 +89,7 @@ location of your Java installation."
 fi
 
 # Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
     MAX_FD_LIMIT=`ulimit -H -n`
     if [ $? -eq 0 ] ; then
         if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then

+ 3 - 3
frameworks/Java/comsat-servlet/gradlew.bat

@@ -8,14 +8,14 @@
 @rem Set local scope for the variables with windows NT shell
 if "%OS%"=="Windows_NT" setlocal
 
-@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS=
-
 set DIRNAME=%~dp0
 if "%DIRNAME%" == "" set DIRNAME=.
 set APP_BASE_NAME=%~n0
 set APP_HOME=%DIRNAME%
 
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
 @rem Find java.exe
 if defined JAVA_HOME goto findJavaFromJavaHome
 

+ 8 - 0
frameworks/Java/comsat-servlet/setup-generic.sh

@@ -0,0 +1,8 @@
+#!/usr/bin/env bash
+
+fw_depends java
+
+$TROOT/gradlew clean capsule
+
+CAPSULE=`ls build/libs/comsat-servlet-*-capsule.jar`
+java -Dcapsule.mode=$MODE -jar $CAPSULE

+ 5 - 0
frameworks/Java/comsat-servlet/setup-jetty.sh

@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+
+MODE="jetty"
+
+. $TROOT/setup-generic.sh

+ 5 - 0
frameworks/Java/comsat-servlet/setup-undertow.sh

@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+
+MODE="undertow"
+
+. $TROOT/setup-generic.sh

+ 2 - 7
frameworks/Java/comsat-servlet/setup.sh

@@ -1,8 +1,3 @@
-#!/bin/bash
+#!/usr/bin/env bash
 
-fw_depends java
-
-$TROOT/gradlew clean capsule
-
-CAPSULE=`ls build/libs/comsat-servlet-*-capsule.jar`
-java -jar $CAPSULE
+. setup-jetty.sh

+ 7 - 2
frameworks/Java/comsat-servlet/source_code

@@ -1,2 +1,7 @@
-./jetty-servlet/src/main/java/hello/
-./jetty-servlet/src/main/java/hello/HelloWebServer.java
+./comsat-servlet/src/main/java/hello/
+./comsat-servlet/src/main/java/hello/HelloWorld.java
+./comsat-servlet/src/main/java/hello/JettyServer.java
+./comsat-servlet/src/main/java/hello/UndertowServer.java
+./comsat-servlet/src/main/java/hello/Server.java
+./comsat-servlet/src/main/java/hello/PlaintextServlet.java
+./comsat-servlet/src/main/java/hello/JsonServlet.java

+ 44 - 0
frameworks/Java/comsat-servlet/src/main/java/hello/JettyServer.java

@@ -0,0 +1,44 @@
+package hello;
+
+import co.paralleluniverse.embedded.containers.AbstractEmbeddedServer;
+import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.util.thread.QueuedThreadPool;
+
+/**
+ * An implementation of the TechEmpower benchmark tests using Comsat servlets and the Jetty servlet container.
+ */
+public final class JettyServer implements Server {
+    @Override
+    public final void run() throws Exception {
+        final org.eclipse.jetty.server.Server s = new org.eclipse.jetty.server.Server(new QueuedThreadPool(200, Runtime.getRuntime().availableProcessors()));
+
+        final ServerConnector http = new ServerConnector(s);
+        http.setReuseAddress(true);
+        http.setAcceptQueueSize(100000);
+        http.setPort(8080);
+        s.addConnector(http);
+
+        final ServletContextHandler context = new ServletContextHandler();
+        context.setContextPath("/");
+
+        final ServletHolder holder1 = new ServletHolder(new PlaintextServlet());
+        context.addServlet(holder1, "/plaintext");
+        holder1.setAsyncSupported(true);
+        final ServletHolder holder2 = new ServletHolder(new JsonServlet());
+        context.addServlet(holder2, "/json");
+        holder2.setAsyncSupported(true);
+
+        s.setHandler(context);
+
+        s.start();
+        System.err.println("Server is up.");
+
+        AbstractEmbeddedServer.waitUrlAvailable("http://localhost:8080/plaintext");
+        AbstractEmbeddedServer.waitUrlAvailable("http://localhost:8080/json");
+        System.err.println("Server test cases are instrumented and bootstrapped.");
+
+        s.join();
+    }
+}

+ 27 - 0
frameworks/Java/comsat-servlet/src/main/java/hello/JsonServlet.java

@@ -0,0 +1,27 @@
+package hello;
+
+import co.paralleluniverse.fibers.Suspendable;
+import co.paralleluniverse.fibers.servlet.FiberHttpServlet;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+public final class JsonServlet extends FiberHttpServlet {
+    private static final class HelloWorldData {
+        @SuppressWarnings("unused")
+        public final String message = "Hello, World!";
+    }
+
+    private static final ObjectMapper mapper = new ObjectMapper();
+
+    @Override
+    @Suspendable
+    protected final void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
+        resp.setContentType("application/json");
+        resp.setHeader("Server", "comsat-servlet-undertow");
+        mapper.writeValue(resp.getOutputStream(), new HelloWorldData());
+    }
+}

+ 22 - 0
frameworks/Java/comsat-servlet/src/main/java/hello/PlaintextServlet.java

@@ -0,0 +1,22 @@
+package hello;
+
+import co.paralleluniverse.fibers.Suspendable;
+import co.paralleluniverse.fibers.servlet.FiberHttpServlet;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+
+public final class PlaintextServlet extends FiberHttpServlet {
+    private static final byte[] helloWorld = "Hello, World!".getBytes(StandardCharsets.ISO_8859_1);
+
+    @Override
+    @Suspendable
+    protected final void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
+        resp.setContentType("text/plain");
+        resp.setHeader("Server", "comsat-servlet-undertow");
+        resp.getOutputStream().write(helloWorld);
+    }
+}

+ 6 - 0
frameworks/Java/comsat-servlet/src/main/java/hello/Server.java

@@ -0,0 +1,6 @@
+package hello;
+
+@FunctionalInterface
+public interface Server {
+    void run() throws Exception;
+}

+ 9 - 40
frameworks/Java/comsat-servlet/src/main/java/hello/HelloWebServer.java → frameworks/Java/comsat-servlet/src/main/java/hello/UndertowServer.java

@@ -1,9 +1,6 @@
 package hello;
 
 import co.paralleluniverse.embedded.containers.AbstractEmbeddedServer;
-import co.paralleluniverse.fibers.Suspendable;
-import co.paralleluniverse.fibers.servlet.FiberHttpServlet;
-import com.fasterxml.jackson.databind.ObjectMapper;
 import io.undertow.Undertow;
 import io.undertow.UndertowOptions;
 import io.undertow.server.HttpHandler;
@@ -12,46 +9,14 @@ import io.undertow.servlet.api.DeploymentInfo;
 import io.undertow.servlet.api.DeploymentManager;
 import org.xnio.Options;
 
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
-import java.nio.charset.StandardCharsets;
 
 /**
  * An implementation of the TechEmpower benchmark tests using Comsat servlets and the Undertow servlet container.
  */
-public final class HelloWebServer {
-    private static final class JsonServlet extends FiberHttpServlet {
-        private static final class HelloWorldData {
-            @SuppressWarnings("unused")
-            public final String message = "Hello, World!";
-        }
-
-        private static final ObjectMapper mapper = new ObjectMapper();
-
-        @Override
-        @Suspendable
-        protected final void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
-            resp.setContentType("application/json");
-            resp.setHeader("Server", "comsat-servlet-undertow");
-            mapper.writeValue(resp.getOutputStream(), new HelloWorldData());
-        }
-    }
-
-    private static final class PlaintextServlet extends FiberHttpServlet {
-        private static final byte[] helloWorld = "Hello, World!".getBytes(StandardCharsets.ISO_8859_1);
-
-        @Override
-        @Suspendable
-        protected final void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
-            resp.setContentType("text/plain");
-            resp.setHeader("Server", "comsat-servlet-undertow");
-            resp.getOutputStream().write(helloWorld);
-        }
-    }
-
-    public static void main(String[] args) throws Exception {
+public final class UndertowServer implements Server {
+    @Override
+    public final void run() throws Exception {
         final DeploymentInfo deployment = Servlets.deployment().setDeploymentName("")
             .setClassLoader(ClassLoader.getSystemClassLoader())
             .setContextPath("/");
@@ -73,6 +38,9 @@ public final class HelloWebServer {
             .setIoThreads(100)
             .setWorkerThreads(100)
 
+            .setServerOption(Options.CONNECTION_HIGH_WATER, 100_000)
+            .setServerOption(Options.CONNECTION_LOW_WATER, 100_000)
+
             .setBufferSize(1024)
             .setBuffersPerRegion(100)
 
@@ -80,7 +48,8 @@ public final class HelloWebServer {
             .setSocketOption(Options.REUSE_ADDRESSES, true)
             // .setSocketOption(Options.CORK, true)
             // .setSocketOption(Options.USE_DIRECT_BUFFERS, true)
-            // .setSocketOption(Options.BACKLOG, Integer.MAX_VALUE)
+            .setSocketOption(Options.BACKLOG, 100000)
+            .setSocketOption(Options.TCP_NODELAY, true)
             // .setSocketOption(Options.RECEIVE_BUFFER, 2048)
             // .setSocketOption(Options.SEND_BUFFER, 2048)
             // .setSocketOption(Options.CONNECTION_HIGH_WATER, Integer.MAX_VALUE)
@@ -107,7 +76,7 @@ public final class HelloWebServer {
                     server.stop();
 
                     System.err.println("Server is down.");
-                } catch (Exception e) {
+                } catch (final Exception e) {
                     throw new RuntimeException(e);
                 }
             }

+ 10 - 0
frameworks/Java/comsat-servlet/src/main/java/hello/World.java

@@ -0,0 +1,10 @@
+package hello;
+
+public final class World {
+    public static void main(String[] args) throws Exception {
+        final Server s = (Server) Class.forName(System.getProperty("serverClass", "hello.JettyServer")).newInstance();
+        s.run();
+    }
+
+    private World() {}
+}

+ 3 - 2
frameworks/Java/comsat-webactors/README.md

@@ -10,8 +10,9 @@ This is the [Parallel Universe Comsat Web Actors](http://docs.paralleluniverse.c
 
 * Jackson JSON 2.7.0 (https://github.com/FasterXML/jackson)
 * Quasar 0.7.4 (http://docs.paralleluniverse.co/quasar)
-* Comsat 0.6.0-SNAPSHOT (http://docs.paralleluniverse.co/comsat)
-* Netty 4.0.33.Final (http://undertow.io)
+* Comsat 0.7.0 (http://docs.paralleluniverse.co/comsat)
+* Netty 4.0.36.Final (http://netty.io/)
+* Undertow 1.3.19 Final (http://undertow.io)
 
 ## Test URLs
 

+ 20 - 1
frameworks/Java/comsat-webactors/benchmark_config.json

@@ -14,12 +14,31 @@
         "language": "Java",
         "orm": "Raw",
         "platform": "Comsat Web Actors",
-        "webserver": "Undertow",
+        "webserver": "Netty",
         "os": "Linux",
         "database_os": "Linux",
         "display_name": "comsat-actors-netty",
         "notes": "Comsat Web Actors run as Netty handler",
         "versus": ""
+      },
+      "undertow": {
+        "setup_file": "setup-undertow",
+        "json_url": "/json",
+        "plaintext_url": "/plaintext",
+        "port": 8080,
+        "approach": "Realistic",
+        "classification": "Platform",
+        "database": "None",
+        "framework": "comsat-webactors",
+        "language": "Java",
+        "orm": "Raw",
+        "platform": "Comsat Web Actors",
+        "webserver": "Undertow",
+        "os": "Linux",
+        "database_os": "Linux",
+        "display_name": "comsat-actors-undertow",
+        "notes": "Comsat Web Actors run as Undertow handler",
+        "versus": ""
       }
     }
   ]

+ 31 - 7
frameworks/Java/comsat-webactors/build.gradle

@@ -8,12 +8,17 @@ apply plugin: 'java'
 sourceCompatibility = 1.8
 targetCompatibility = 1.8
 
-version = '0.2'
+version = '0.3'
 
-ext.jacksonVer = '2.7.0'
-ext.quasarVer  = '0.7.4'
-ext.comsatVer  = '0.6.0'
-ext.capsuleVer = '1.0.1'
+ext.jacksonVer  = '2.7.4'
+ext.quasarVer   = '0.7.5'
+ext.comsatVer   = '0.7.0'
+ext.capsuleVer  = '1.0.2'
+
+ext.nettyVer    = '4.0.37.Final'
+ext.undertowVer = '1.3.22.Final'
+
+ext.slf4jVer    = '1.7.21'
 
 [compileJava, compileTestJava]*.options*.encoding = "UTF-8"
 
@@ -27,6 +32,16 @@ configurations {
     quasar
 }
 
+configurations.all {
+    resolutionStrategy {
+        failOnVersionConflict()
+        force "io.netty:netty-all:$nettyVer"
+        force "io.undertow:undertow-core:$undertowVer"
+        force "org.slf4j:slf4j-api:$slf4jVer"
+        force "co.paralleluniverse:quasar-actors:$quasarVer"
+    }
+}
+
 configurations.capsule.dependencies.clear()
 
 dependencies {
@@ -34,6 +49,7 @@ dependencies {
     compile "com.fasterxml.jackson.core:jackson-databind:$jacksonVer"
     compile "co.paralleluniverse:comsat-actors-api:$comsatVer"
     compile "co.paralleluniverse:comsat-actors-netty:$comsatVer"
+    compile "co.paralleluniverse:comsat-actors-undertow:$comsatVer"
     compile "co.paralleluniverse:comsat-test-utils:$comsatVer"
 
     capsule "co.paralleluniverse:capsule:$capsuleVer"
@@ -42,13 +58,21 @@ dependencies {
 }
 
 task capsule(type: FatCapsule) {
-    applicationClass "hello.HelloWebActor"
+    applicationClass "hello.World"
 
     capsuleManifest {
         javaAgents = [configurations.quasar.iterator().next().getName()]
+
+        mode('netty') {
+            systemProperties['serverClass'] = 'hello.NettyServer'
+        }
+
+        mode('undertow') {
+            systemProperties['serverClass'] = 'hello.UndertowServer'
+        }
     }
 }
 
 task wrapper(type: Wrapper) {
-    gradleVersion = '2.11'
+    gradleVersion = '2.14'
 }

BIN
frameworks/Java/comsat-webactors/gradle/wrapper/gradle-wrapper.jar


+ 2 - 2
frameworks/Java/comsat-webactors/gradle/wrapper/gradle-wrapper.properties

@@ -1,6 +1,6 @@
-#Tue Feb 09 20:07:28 IST 2016
+#Wed Jun 15 10:12:59 IDT 2016
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-2.11-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.14-bin.zip

+ 25 - 21
frameworks/Java/comsat-webactors/gradlew

@@ -6,12 +6,30 @@
 ##
 ##############################################################################
 
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS=""
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
 
 APP_NAME="Gradle"
 APP_BASE_NAME=`basename "$0"`
 
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
 # Use the maximum available, or set MAX_FD != -1 to use that value.
 MAX_FD="maximum"
 
@@ -30,6 +48,7 @@ die ( ) {
 cygwin=false
 msys=false
 darwin=false
+nonstop=false
 case "`uname`" in
   CYGWIN* )
     cygwin=true
@@ -40,26 +59,11 @@ case "`uname`" in
   MINGW* )
     msys=true
     ;;
+  NONSTOP* )
+    nonstop=true
+    ;;
 esac
 
-# Attempt to set APP_HOME
-# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
-    ls=`ls -ld "$PRG"`
-    link=`expr "$ls" : '.*-> \(.*\)$'`
-    if expr "$link" : '/.*' > /dev/null; then
-        PRG="$link"
-    else
-        PRG=`dirname "$PRG"`"/$link"
-    fi
-done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
-APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
-
 CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
 
 # Determine the Java command to use to start the JVM.
@@ -85,7 +89,7 @@ location of your Java installation."
 fi
 
 # Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
     MAX_FD_LIMIT=`ulimit -H -n`
     if [ $? -eq 0 ] ; then
         if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then

+ 3 - 3
frameworks/Java/comsat-webactors/gradlew.bat

@@ -8,14 +8,14 @@
 @rem Set local scope for the variables with windows NT shell
 if "%OS%"=="Windows_NT" setlocal
 
-@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS=
-
 set DIRNAME=%~dp0
 if "%DIRNAME%" == "" set DIRNAME=.
 set APP_BASE_NAME=%~n0
 set APP_HOME=%DIRNAME%
 
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
 @rem Find java.exe
 if defined JAVA_HOME goto findJavaFromJavaHome
 

+ 8 - 0
frameworks/Java/comsat-webactors/setup-generic.sh

@@ -0,0 +1,8 @@
+#!/usr/bin/env bash
+
+fw_depends java
+
+$TROOT/gradlew clean capsule
+
+CAPSULE=`ls build/libs/comsat-webactors-*-capsule.jar`
+java -Dcapsule.mode=$MODE -jar $CAPSULE

+ 5 - 0
frameworks/Java/comsat-webactors/setup-netty.sh

@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+
+MODE="netty"
+
+. $TROOT/setup-generic.sh

+ 5 - 0
frameworks/Java/comsat-webactors/setup-undertow.sh

@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+
+MODE="undertow"
+
+. $TROOT/setup-generic.sh

+ 2 - 8
frameworks/Java/comsat-webactors/setup.sh

@@ -1,9 +1,3 @@
-#!/bin/bash
+#!/usr/bin/env bash
 
-fw_depends java
-
-$TROOT/gradlew capsule
-
-CAPSULE=`ls build/libs/comsat-webactors-*-capsule.jar`
-
-java -Dcapsule.mode=$MODE -jar $CAPSULE
+. setup-netty.sh

+ 5 - 1
frameworks/Java/comsat-webactors/source_code

@@ -1,2 +1,6 @@
 ./src/main/java/hello/
-./src/main/java/hello/HelloWebActor
+./src/main/java/hello/WebActor
+./src/main/java/hello/World
+./src/main/java/hello/NettyServer
+./src/main/java/hello/UndertowServer
+./src/main/java/hello/Server

+ 0 - 159
frameworks/Java/comsat-webactors/src/main/java/hello/HelloWebActor.java

@@ -1,159 +0,0 @@
-package hello;
-
-import co.paralleluniverse.actors.Actor;
-import co.paralleluniverse.actors.ActorRef;
-import co.paralleluniverse.actors.BasicActor;
-import co.paralleluniverse.comsat.webactors.HttpRequest;
-import co.paralleluniverse.comsat.webactors.HttpResponse;
-
-import co.paralleluniverse.comsat.webactors.WebMessage;
-import co.paralleluniverse.comsat.webactors.netty.WebActorHandler;
-import co.paralleluniverse.embedded.containers.AbstractEmbeddedServer;
-import co.paralleluniverse.fibers.SuspendExecution;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import io.netty.bootstrap.ServerBootstrap;
-import io.netty.buffer.PooledByteBufAllocator;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.channel.ChannelInitializer;
-import io.netty.channel.ChannelOption;
-import io.netty.channel.ChannelPipeline;
-import io.netty.channel.nio.NioEventLoopGroup;
-import io.netty.channel.socket.SocketChannel;
-import io.netty.channel.socket.nio.NioServerSocketChannel;
-import io.netty.handler.codec.http.FullHttpRequest;
-import io.netty.handler.codec.http.HttpObjectAggregator;
-import io.netty.handler.codec.http.HttpRequestDecoder;
-import io.netty.handler.codec.http.HttpResponseEncoder;
-
-import java.nio.ByteBuffer;
-// import java.text.SimpleDateFormat;
-// import java.util.Locale;
-// import java.util.TimeZone;
-
-import static co.paralleluniverse.comsat.webactors.HttpResponse.error;
-import static co.paralleluniverse.comsat.webactors.HttpResponse.ok;
-
-public final class HelloWebActor extends BasicActor<Object, Void> {
-    /////////////////// WEB ACTOR PART ///////////////////
-
-    private static final String HELLO_WORLD = "Hello, World!";
-    private static final byte[] HELLO_WORLD_A = HELLO_WORLD.getBytes();
-
-    private static final class HelloWorldData {
-        @SuppressWarnings("unused")
-        public final String message = HELLO_WORLD;
-    }
-
-    private static final ObjectMapper mapper = new ObjectMapper();
-
-//    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
-//    static {
-//        dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
-//    }
-
-    @Override
-    protected final Void doRun() throws InterruptedException, SuspendExecution {
-        //noinspection InfiniteLoopStatement
-        for (; ; ) {
-            final Object message = receive();
-            if (message instanceof HttpRequest) {
-                final HttpRequest req = (HttpRequest) message;
-                HttpResponse.Builder res;
-                final String s = req.getRequestURI();
-                if ("/plaintext".equals(s)) {
-                    final ByteBuffer b = ByteBuffer.wrap(HELLO_WORLD_A);
-                    res = ok(self(), req, b).setContentType("text/plain");
-                } else if ("/json".equals(s)) {
-                    try {
-                        res = ok(self(), req, mapper.writeValueAsString(new HelloWorldData())).setContentType("application/json");
-                    } catch (final JsonProcessingException e) {
-                        throw new RuntimeException(e);
-                    }
-                } else {
-                    res = error(self(), req, 404, "Not found");
-                }
-                req.getFrom().send(
-                    res
-                        .addHeader("Server", "comsat-webactors")
-//                        .addHeader("Date", dateFormat.format(calendar.getTime()))
-                        .build()
-                );
-            }
-        }
-    }
-
-    /////////////////// SERVER PART ///////////////////
-
-    private static final Actor actor = new HelloWebActor();
-    @SuppressWarnings("unchecked")
-    private static final ActorRef<? extends WebMessage> actorRef = actor.spawn();
-
-    private static final WebActorHandler.DefaultContextImpl context = new MyDefaultContextImpl();
-
-    private static class SocketChannelChannelInitializer extends ChannelInitializer<SocketChannel> {
-        @Override
-        public void initChannel(SocketChannel ch) throws Exception {
-            final ChannelPipeline pipeline = ch.pipeline();
-            pipeline.addLast(new HttpRequestDecoder());
-            pipeline.addLast(new HttpResponseEncoder());
-            pipeline.addLast(new HttpObjectAggregator(65536));
-            pipeline.addLast(new WebActorHandler(new MyWebActorContextProvider()));
-        }
-
-        private static class MyWebActorContextProvider implements WebActorHandler.WebActorContextProvider {
-            @Override
-            public WebActorHandler.Context get(ChannelHandlerContext ctx, FullHttpRequest req) {
-                return context;
-            }
-        }
-    }
-
-    private static class MyDefaultContextImpl extends WebActorHandler.DefaultContextImpl {
-        @SuppressWarnings("unchecked")
-        @Override
-        public ActorRef<? extends WebMessage> getRef() {
-            return actorRef;
-        }
-
-        @Override
-        public final boolean handlesWithWebSocket(String uri) {
-            return false;
-        }
-
-        @Override
-        public final boolean handlesWithHttp(String uri) {
-            return true;
-        }
-
-        @Override
-        public final boolean watch() {
-            return false;
-        }
-    }
-
-    public static void main(String[] args) throws Exception {
-        final ServerBootstrap b = new ServerBootstrap();
-
-        b.option(ChannelOption.SO_BACKLOG, 65535);
-        b.childOption(ChannelOption.CONNECT_TIMEOUT_MILLIS, 0);
-        b.childOption(ChannelOption.TCP_NODELAY, true);
-        b.childOption(ChannelOption.SO_REUSEADDR, true);
-        b.childOption(ChannelOption.SO_LINGER, 0);
-        // b.childOption(ChannelOption.WRITE_BUFFER_HIGH_WATER_MARK, 32 * 1024);
-        // b.childOption(ChannelOption.WRITE_BUFFER_LOW_WATER_MARK, 8 * 1024);
-        b.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
-
-        final ChannelInitializer<SocketChannel> childHandler = new SocketChannelChannelInitializer();
-        final NioEventLoopGroup group = new NioEventLoopGroup();
-        b.group(group)
-            .channel(NioServerSocketChannel.class)
-            .childHandler(childHandler);
-
-        b.bind(8080).sync();
-        System.err.println("Server is up.");
-        AbstractEmbeddedServer.waitUrlAvailable("http://localhost:8080/plaintext");
-        AbstractEmbeddedServer.waitUrlAvailable("http://localhost:8080/json");
-        System.err.println("Server test cases are instrumented and bootstrapped.");
-    }
-}

+ 67 - 0
frameworks/Java/comsat-webactors/src/main/java/hello/NettyServer.java

@@ -0,0 +1,67 @@
+package hello;
+
+import co.paralleluniverse.comsat.webactors.netty.AutoWebActorHandler;
+import co.paralleluniverse.embedded.containers.AbstractEmbeddedServer;
+import io.netty.bootstrap.ServerBootstrap;
+import io.netty.buffer.PooledByteBufAllocator;
+import io.netty.channel.*;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.channel.socket.nio.NioServerSocketChannel;
+import io.netty.handler.codec.http.HttpObjectAggregator;
+import io.netty.handler.codec.http.HttpRequestDecoder;
+import io.netty.handler.codec.http.HttpResponseEncoder;
+
+import java.util.Map;
+import java.util.concurrent.Callable;
+
+public final class NettyServer implements Server {
+    @Override
+    public final void run() throws Exception {
+        WebActor.SERVER = "comsat-webactors-netty";
+        final ServerBootstrap b = new ServerBootstrap();
+
+        b.option(ChannelOption.SO_BACKLOG, 100000);
+        b.childOption(ChannelOption.CONNECT_TIMEOUT_MILLIS, 0);
+        b.childOption(ChannelOption.TCP_NODELAY, true);
+        b.childOption(ChannelOption.SO_REUSEADDR, true);
+        b.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
+
+        final ChannelInitializer<SocketChannel> childHandler = new SocketChannelChannelInitializer(() -> new AutoWebActorHandler() {
+            @Override
+            protected AutoContextProvider newContextProvider(ClassLoader userClassLoader, Map<Class<?>, Object[]> actorParams) {
+                return new AutoContextProvider(userClassLoader, actorParams, 1_000_000L /* ms */);
+            }
+        });
+        final NioEventLoopGroup group = new NioEventLoopGroup(200);
+        b.group(group)
+            .channel(NioServerSocketChannel.class)
+            .childHandler(childHandler);
+
+        final ChannelFuture cf = b.bind(8080);
+        cf.sync();
+
+        System.err.println("Server is up.");
+
+        AbstractEmbeddedServer.waitUrlAvailable("http://localhost:8080/plaintext");
+        AbstractEmbeddedServer.waitUrlAvailable("http://localhost:8080/json");
+        System.err.println("Server test cases are instrumented and bootstrapped.");
+    }
+
+    private static final class SocketChannelChannelInitializer extends ChannelInitializer<SocketChannel> {
+        private final Callable<SimpleChannelInboundHandler<Object>> handlerProvider;
+
+        public SocketChannelChannelInitializer(Callable<SimpleChannelInboundHandler<Object>> handlerProvider) {
+            this.handlerProvider = handlerProvider;
+        }
+
+        @Override
+        public final void initChannel(SocketChannel ch) throws Exception {
+            final ChannelPipeline pipeline = ch.pipeline();
+            pipeline.addLast(new HttpRequestDecoder());
+            pipeline.addLast(new HttpResponseEncoder());
+            pipeline.addLast(new HttpObjectAggregator(65536));
+            pipeline.addLast(handlerProvider.call());
+        }
+    }
+}

+ 6 - 0
frameworks/Java/comsat-webactors/src/main/java/hello/Server.java

@@ -0,0 +1,6 @@
+package hello;
+
+@FunctionalInterface
+public interface Server {
+    void run() throws Exception;
+}

+ 55 - 0
frameworks/Java/comsat-webactors/src/main/java/hello/UndertowServer.java

@@ -0,0 +1,55 @@
+package hello;
+
+import co.paralleluniverse.comsat.webactors.undertow.AutoWebActorHandler;
+import co.paralleluniverse.embedded.containers.AbstractEmbeddedServer;
+import io.undertow.Undertow;
+import io.undertow.UndertowOptions;
+import org.xnio.Options;
+
+public final class UndertowServer implements Server {
+    @Override
+    public final void run() throws Exception {
+        WebActor.SERVER = "comsat-webactors-undertow";
+        //noinspection deprecation
+        final Undertow u = io.undertow.Undertow.builder()
+            .setHandler(new AutoWebActorHandler())
+
+            .setIoThreads(100)
+            .setWorkerThreads(100)
+            .setServerOption(Options.CONNECTION_HIGH_WATER, 100_000)
+            .setServerOption(Options.CONNECTION_LOW_WATER, 100_000)
+
+            .setDirectBuffers(true)
+            .setBufferSize(1024)
+            .setBuffersPerRegion(100)
+
+            // .setSocketOption(Options.ALLOW_BLOCKING, true)
+            .setSocketOption(Options.REUSE_ADDRESSES, true)
+            // .setSocketOption(Options.CORK, true)
+            // .setSocketOption(Options.USE_DIRECT_BUFFERS, true)
+            .setSocketOption(Options.BACKLOG, 100000)
+            .setSocketOption(Options.TCP_NODELAY, true)
+            // .setSocketOption(Options.RECEIVE_BUFFER, 2048)
+            // .setSocketOption(Options.SEND_BUFFER, 2048)
+            // .setSocketOption(Options.CONNECTION_HIGH_WATER, Integer.MAX_VALUE)
+            // .setSocketOption(Options.CONNECTION_LOW_WATER, Integer.MAX_VALUE)
+            // .setSocketOption(Options.READ_TIMEOUT, Integer.MAX_VALUE)
+            // .setSocketOption(Options.WRITE_TIMEOUT, Integer.MAX_VALUE)
+            // .setServerOption(UndertowOptions.ALWAYS_SET_KEEP_ALIVE, false) //don't send a keep-alive header for HTTP/1.1 requests, as it is not required
+
+            // .setServerOption(UndertowOptions.ALWAYS_SET_DATE, true)
+            .setServerOption(UndertowOptions.ENABLE_CONNECTOR_STATISTICS, false)
+            .setServerOption(UndertowOptions.RECORD_REQUEST_START_TIME, false)
+
+            .addHttpListener(8080, "0.0.0.0")
+            .build();
+
+        new Thread(u::start).start();
+
+        System.err.println("Server is up.");
+
+        AbstractEmbeddedServer.waitUrlAvailable("http://localhost:8080/plaintext");
+        AbstractEmbeddedServer.waitUrlAvailable("http://localhost:8080/json");
+        System.err.println("Server test cases are instrumented and bootstrapped.");
+    }
+}

+ 57 - 0
frameworks/Java/comsat-webactors/src/main/java/hello/WebActor.java

@@ -0,0 +1,57 @@
+package hello;
+
+import co.paralleluniverse.actors.BasicActor;
+import co.paralleluniverse.comsat.webactors.HttpRequest;
+import co.paralleluniverse.comsat.webactors.HttpResponse;
+
+import co.paralleluniverse.fibers.SuspendExecution;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import java.nio.ByteBuffer;
+
+import static co.paralleluniverse.comsat.webactors.HttpResponse.error;
+import static co.paralleluniverse.comsat.webactors.HttpResponse.ok;
+
[email protected](httpUrlPatterns = {"/*"})
+public final class WebActor extends BasicActor<Object, Void> {
+    static String SERVER = "comsat-webactors";
+
+    private static final String HELLO_WORLD = "Hello, World!";
+    private static final byte[] HELLO_WORLD_A = HELLO_WORLD.getBytes();
+
+    private static final class HelloWorldData {
+        @SuppressWarnings("unused")
+        public final String message = HELLO_WORLD;
+    }
+
+    private static final ObjectMapper mapper = new ObjectMapper();
+
+    @Override
+    protected final Void doRun() throws InterruptedException, SuspendExecution {
+        final Object message = receive();
+        if (message instanceof HttpRequest) {
+            final HttpRequest req = (HttpRequest) message;
+            HttpResponse.Builder res;
+            final String s = req.getRequestURI();
+            if ("/plaintext".equals(s)) {
+                final ByteBuffer b = ByteBuffer.wrap(HELLO_WORLD_A);
+                res = ok(self(), req, b).setContentType("text/plain");
+            } else if ("/json".equals(s)) {
+                try {
+                    res = ok(self(), req, mapper.writeValueAsString(new HelloWorldData())).setContentType("application/json");
+                } catch (final JsonProcessingException e) {
+                    throw new RuntimeException(e);
+                }
+            } else {
+                res = error(self(), req, 404, "Not found");
+            }
+            req.getFrom().send (
+                res
+                    .addHeader("Server", SERVER)
+                    .build()
+            );
+        }
+        return null;
+    }
+}

+ 10 - 0
frameworks/Java/comsat-webactors/src/main/java/hello/World.java

@@ -0,0 +1,10 @@
+package hello;
+
+public final class World {
+    public static void main(String[] args) throws Exception {
+        final Server s = (Server) Class.forName(System.getProperty("serverClass", "hello.WebActor")).newInstance();
+        s.run();
+    }
+
+    private World() {}
+}