You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@openwhisk.apache.org by GitBox <gi...@apache.org> on 2017/10/20 23:53:04 UTC

[GitHub] csantanapr closed pull request #2: Added support for configurable java action method name

csantanapr closed pull request #2: Added support for configurable java action method name
URL: https://github.com/apache/incubator-openwhisk-runtime-java/pull/2
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..489e504
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,10 @@
+# Java 8 OpenWhisk Runtime Container
+
+
+## 1.0.1
+Changes: 
+- Allow custom name for main Class
+
+## 1.0.0
+Changes: 
+- Initial release
diff --git a/core/javaAction/proxy/src/main/java/openwhisk/java/action/JarLoader.java b/core/javaAction/proxy/src/main/java/openwhisk/java/action/JarLoader.java
index 13bf617..76de8f0 100644
--- a/core/javaAction/proxy/src/main/java/openwhisk/java/action/JarLoader.java
+++ b/core/javaAction/proxy/src/main/java/openwhisk/java/action/JarLoader.java
@@ -52,13 +52,17 @@ public static Path saveBase64EncodedFile(InputStream encoded) throws Exception {
         return destinationPath;
     }
 
-    public JarLoader(Path jarPath, String mainClassName)
+    public JarLoader(Path jarPath, String entrypoint)
             throws MalformedURLException, ClassNotFoundException, NoSuchMethodException, SecurityException {
         super(new URL[] { jarPath.toUri().toURL() });
 
-        this.mainClass = loadClass(mainClassName);
+        final String[] splittedEntrypoint = entrypoint.split("#");
+        final String entrypointClassName = splittedEntrypoint[0];
+        final String entrypointMethodName = splittedEntrypoint.length > 1 ? splittedEntrypoint[1] : "main";
 
-        Method m = mainClass.getMethod("main", new Class[] { JsonObject.class });
+        this.mainClass = loadClass(entrypointClassName);
+
+        Method m = mainClass.getMethod(entrypointMethodName, new Class[] { JsonObject.class });
         m.setAccessible(true);
         int modifiers = m.getModifiers();
         if (m.getReturnType() != JsonObject.class || !Modifier.isStatic(modifiers) || !Modifier.isPublic(modifiers)) {
diff --git a/tests/src/test/scala/actionContainers/JavaActionContainerTests.scala b/tests/src/test/scala/actionContainers/JavaActionContainerTests.scala
index 297a8f6..7992892 100644
--- a/tests/src/test/scala/actionContainers/JavaActionContainerTests.scala
+++ b/tests/src/test/scala/actionContainers/JavaActionContainerTests.scala
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package runtime.actionContainers
+package actionContainers
 
 import org.junit.runner.RunWith
 import org.scalatest.FlatSpec
@@ -55,24 +55,25 @@ class JavaActionContainerTests extends FlatSpec with Matchers with WskActorSyste
       withJavaContainer(
         { c =>
           val jar = JarBuilder.mkBase64Jar(
-            Seq("example", "HelloWhisk.java") -> """
-                    | package example;
-                    |
-                    | import com.google.gson.JsonObject;
-                    |
-                    | public class HelloWhisk {
-                    |     public static JsonObject main(JsonObject args) {
-                    |         JsonObject response = new JsonObject();
-                    |         response.addProperty("api_host", System.getenv("__OW_API_HOST"));
-                    |         response.addProperty("api_key", System.getenv("__OW_API_KEY"));
-                    |         response.addProperty("namespace", System.getenv("__OW_NAMESPACE"));
-                    |         response.addProperty("action_name", System.getenv("__OW_ACTION_NAME"));
-                    |         response.addProperty("activation_id", System.getenv("__OW_ACTIVATION_ID"));
-                    |         response.addProperty("deadline", System.getenv("__OW_DEADLINE"));
-                    |         return response;
-                    |     }
-                    | }
-                """.stripMargin.trim)
+            Seq("example", "HelloWhisk.java") ->
+              """
+                | package example;
+                |
+                | import com.google.gson.JsonObject;
+                |
+                | public class HelloWhisk {
+                |     public static JsonObject main(JsonObject args) {
+                |         JsonObject response = new JsonObject();
+                |         response.addProperty("api_host", System.getenv("__OW_API_HOST"));
+                |         response.addProperty("api_key", System.getenv("__OW_API_KEY"));
+                |         response.addProperty("namespace", System.getenv("__OW_NAMESPACE"));
+                |         response.addProperty("action_name", System.getenv("__OW_ACTION_NAME"));
+                |         response.addProperty("activation_id", System.getenv("__OW_ACTIVATION_ID"));
+                |         response.addProperty("deadline", System.getenv("__OW_DEADLINE"));
+                |         return response;
+                |     }
+                | }
+              """.stripMargin.trim)
 
           val (initCode, _) = c.init(initPayload("example.HelloWhisk", jar))
           initCode should be(200)
@@ -93,20 +94,21 @@ class JavaActionContainerTests extends FlatSpec with Matchers with WskActorSyste
   it should "support valid flows" in {
     val (out, err) = withJavaContainer { c =>
       val jar = JarBuilder.mkBase64Jar(
-        Seq("example", "HelloWhisk.java") -> """
-                    | package example;
-                    |
-                    | import com.google.gson.JsonObject;
-                    |
-                    | public class HelloWhisk {
-                    |     public static JsonObject main(JsonObject args) {
-                    |         String name = args.getAsJsonPrimitive("name").getAsString();
-                    |         JsonObject response = new JsonObject();
-                    |         response.addProperty("greeting", "Hello " + name + "!");
-                    |         return response;
-                    |     }
-                    | }
-                """.stripMargin.trim)
+        Seq("example", "HelloWhisk.java") ->
+          """
+            | package example;
+            |
+            | import com.google.gson.JsonObject;
+            |
+            | public class HelloWhisk {
+            |     public static JsonObject main(JsonObject args) {
+            |         String name = args.getAsJsonPrimitive("name").getAsString();
+            |         JsonObject response = new JsonObject();
+            |         response.addProperty("greeting", "Hello " + name + "!");
+            |         return response;
+            |     }
+            | }
+          """.stripMargin.trim)
 
       val (initCode, _) = c.init(initPayload("example.HelloWhisk", jar))
       initCode should be(200)
@@ -124,25 +126,95 @@ class JavaActionContainerTests extends FlatSpec with Matchers with WskActorSyste
     err.trim shouldBe empty
   }
 
+  it should "support valid actions with non 'main' names" in {
+    val (out, err) = withJavaContainer { c =>
+      val jar = JarBuilder.mkBase64Jar(
+        Seq("example", "HelloWhisk.java") ->
+          """
+            | package example;
+            |
+            | import com.google.gson.JsonObject;
+            |
+            | public class HelloWhisk {
+            |     public static JsonObject hello(JsonObject args) {
+            |         String name = args.getAsJsonPrimitive("name").getAsString();
+            |         JsonObject response = new JsonObject();
+            |         response.addProperty("greeting", "Hello " + name + "!");
+            |         return response;
+            |     }
+            | }
+          """.stripMargin.trim)
+
+      val (initCode, _) = c.init(initPayload("example.HelloWhisk#hello", jar))
+      initCode should be(200)
+
+      val (runCode, out) = c.run(runPayload(JsObject("name" -> JsString("Whisk"))))
+      runCode should be(200)
+      out should be(Some(JsObject("greeting" -> JsString("Hello Whisk!"))))
+    }
+
+    out.trim shouldBe empty
+    err.trim shouldBe empty
+  }
+
+  it should "report an error if explicit 'main' is not found" in {
+    val (out, err) = withJavaContainer { c =>
+      val jar = JarBuilder.mkBase64Jar(
+        Seq("example", "HelloWhisk.java") ->
+          """
+            | package example;
+            |
+            | import com.google.gson.JsonObject;
+            |
+            | public class HelloWhisk {
+            |     public static JsonObject hello(JsonObject args) {
+            |         String name = args.getAsJsonPrimitive("name").getAsString();
+            |         JsonObject response = new JsonObject();
+            |         response.addProperty("greeting", "Hello " + name + "!");
+            |         return response;
+            |     }
+            | }
+          """.stripMargin.trim)
+
+      Seq("", "x", "!", "#", "#main", "#bogus").foreach { m =>
+        val (initCode, out) = c.init(initPayload(s"example.HelloWhisk$m", jar))
+        initCode shouldBe 502
+
+        out shouldBe {
+          val error = m match {
+            case c if c == "x" || c == "!" => s"java.lang.ClassNotFoundException: example.HelloWhisk$c"
+            case "#bogus"                  => "java.lang.NoSuchMethodException: example.HelloWhisk.bogus(com.google.gson.JsonObject)"
+            case _                         => "java.lang.NoSuchMethodException: example.HelloWhisk.main(com.google.gson.JsonObject)"
+          }
+          Some(JsObject("error" -> s"An error has occurred (see logs for details): $error".toJson))
+        }
+      }
+    }
+
+    out.trim shouldBe empty
+    err.trim should not be empty
+  }
+
   it should "handle unicode in source, input params, logs, and result" in {
     val (out, err) = withJavaContainer { c =>
       val jar = JarBuilder.mkBase64Jar(
-        Seq("example", "HelloWhisk.java") -> """
-                    | package example;
-                    |
-                    | import com.google.gson.JsonObject;
-                    |
-                    | public class HelloWhisk {
-                    |     public static JsonObject main(JsonObject args) {
-                    |         String delimiter = args.getAsJsonPrimitive("delimiter").getAsString();
-                    |         JsonObject response = new JsonObject();
-                    |          String str = delimiter + " ? " + delimiter;
-                    |          System.out.println(str);
-                    |          response.addProperty("winter", str);
-                    |          return response;
-                    |     }
-                    | }
-            """.stripMargin)
+        Seq("example", "HelloWhisk.java") ->
+          """
+            | package example;
+            |
+            | import com.google.gson.JsonObject;
+            |
+            | public class HelloWhisk {
+            |     public static JsonObject main(JsonObject args) {
+            |         String delimiter = args.getAsJsonPrimitive("delimiter").getAsString();
+            |         JsonObject response = new JsonObject();
+            |          String str = delimiter + " ? " + delimiter;
+            |          System.out.println(str);
+            |          response.addProperty("winter", str);
+            |          return response;
+            |     }
+            | }
+          """.stripMargin)
 
       val (initCode, _) = c.init(initPayload("example.HelloWhisk", jar))
       val (runCode, runRes) = c.run(runPayload(JsObject("delimiter" -> JsString("?"))))
@@ -175,17 +247,18 @@ class JavaActionContainerTests extends FlatSpec with Matchers with WskActorSyste
   it should "return some error on action error" in {
     val (out, err) = withJavaContainer { c =>
       val jar = JarBuilder.mkBase64Jar(
-        Seq("example", "HelloWhisk.java") -> """
-                    | package example;
-                    |
-                    | import com.google.gson.JsonObject;
-                    |
-                    | public class HelloWhisk {
-                    |     public static JsonObject main(JsonObject args) throws Exception {
-                    |         throw new Exception("noooooooo");
-                    |     }
-                    | }
-                """.stripMargin.trim)
+        Seq("example", "HelloWhisk.java") ->
+          """
+            | package example;
+            |
+            | import com.google.gson.JsonObject;
+            |
+            | public class HelloWhisk {
+            |     public static JsonObject main(JsonObject args) throws Exception {
+            |         throw new Exception("noooooooo");
+            |     }
+            | }
+          """.stripMargin.trim)
 
       val (initCode, _) = c.init(initPayload("example.HelloWhisk", jar))
       initCode should be(200)
@@ -204,19 +277,20 @@ class JavaActionContainerTests extends FlatSpec with Matchers with WskActorSyste
   it should "support application errors" in {
     val (out, err) = withJavaContainer { c =>
       val jar = JarBuilder.mkBase64Jar(
-        Seq("example", "Error.java") -> """
-                    | package example;
-                    |
-                    | import com.google.gson.JsonObject;
-                    |
-                    | public class Error {
-                    |     public static JsonObject main(JsonObject args) throws Exception {
-                    |         JsonObject error = new JsonObject();
-                    |         error.addProperty("error", "This action is unhappy.");
-                    |         return error;
-                    |     }
-                    | }
-                """.stripMargin.trim)
+        Seq("example", "Error.java") ->
+          """
+            | package example;
+            |
+            | import com.google.gson.JsonObject;
+            |
+            | public class Error {
+            |     public static JsonObject main(JsonObject args) throws Exception {
+            |         JsonObject error = new JsonObject();
+            |         error.addProperty("error", "This action is unhappy.");
+            |         return error;
+            |     }
+            | }
+          """.stripMargin.trim)
 
       val (initCode, _) = c.init(initPayload("example.Error", jar))
       initCode should be(200)
@@ -234,19 +308,20 @@ class JavaActionContainerTests extends FlatSpec with Matchers with WskActorSyste
 
   it should "survive System.exit" in {
     val (out, err) = withJavaContainer { c =>
-      val jar =
-        JarBuilder.mkBase64Jar(Seq("example", "Quitter.java") -> """
-                    | package example;
-                    |
-                    | import com.google.gson.*;
-                    |
-                    | public class Quitter {
-                    |     public static JsonObject main(JsonObject main) {
-                    |         System.exit(1);
-                    |         return new JsonObject();
-                    |     }
-                    | }
-                """.stripMargin.trim)
+      val jar = JarBuilder.mkBase64Jar(
+        Seq("example", "Quitter.java") ->
+          """
+            | package example;
+            |
+            | import com.google.gson.*;
+            |
+            | public class Quitter {
+            |     public static JsonObject main(JsonObject main) {
+            |         System.exit(1);
+            |         return new JsonObject();
+            |     }
+            | }
+          """.stripMargin.trim)
 
       val (initCode, _) = c.init(initPayload("example.Quitter", jar))
       initCode should be(200)
@@ -264,18 +339,19 @@ class JavaActionContainerTests extends FlatSpec with Matchers with WskActorSyste
 
   it should "enforce that the user returns an object" in {
     withJavaContainer { c =>
-      val jar =
-        JarBuilder.mkBase64Jar(Seq("example", "Nuller.java") -> """
-                    | package example;
-                    |
-                    | import com.google.gson.*;
-                    |
-                    | public class Nuller {
-                    |     public static JsonObject main(JsonObject args) {
-                    |         return null;
-                    |     }
-                    | }
-                """.stripMargin.trim)
+      val jar = JarBuilder.mkBase64Jar(
+        Seq("example", "Nuller.java") ->
+          """
+            | package example;
+            |
+            | import com.google.gson.*;
+            |
+            | public class Nuller {
+            |     public static JsonObject main(JsonObject args) {
+            |         return null;
+            |     }
+            | }
+          """.stripMargin.trim)
 
       val (initCode, _) = c.init(initPayload("example.Nuller", jar))
       initCode should be(200)
@@ -290,43 +366,45 @@ class JavaActionContainerTests extends FlatSpec with Matchers with WskActorSyste
 
   val dynamicLoadingJar = JarBuilder.mkBase64Jar(
     Seq(
-      Seq("example", "EntryPoint.java") -> """
-                | package example;
-                |
-                | import com.google.gson.*;
-                | import java.lang.reflect.*;
-                |
-                | public class EntryPoint {
-                |     private final static String CLASS_NAME = "example.DynamicClass";
-                |     public static JsonObject main(JsonObject args) throws Exception {
-                |         String cl = args.getAsJsonPrimitive("classLoader").getAsString();
-                |
-                |         Class d = null;
-                |         if("local".equals(cl)) {
-                |             d = Class.forName(CLASS_NAME);
-                |         } else if("thread".equals(cl)) {
-                |             d = Thread.currentThread().getContextClassLoader().loadClass(CLASS_NAME);
-                |         }
-                |
-                |         Object o = d.newInstance();
-                |         Method m = o.getClass().getMethod("getMessage");
-                |         String msg = (String)m.invoke(o);
-                |
-                |         JsonObject response = new JsonObject();
-                |         response.addProperty("message", msg);
-                |         return response;
-                |     }
-                | }
-                |""".stripMargin.trim,
-      Seq("example", "DynamicClass.java") -> """
-                | package example;
-                |
-                | public class DynamicClass {
-                |     public String getMessage() {
-                |         return "dynamic!";
-                |     }
-                | }
-                |""".stripMargin.trim))
+      Seq("example", "EntryPoint.java") ->
+        """
+          | package example;
+          |
+          | import com.google.gson.*;
+          | import java.lang.reflect.*;
+          |
+          | public class EntryPoint {
+          |     private final static String CLASS_NAME = "example.DynamicClass";
+          |     public static JsonObject main(JsonObject args) throws Exception {
+          |         String cl = args.getAsJsonPrimitive("classLoader").getAsString();
+          |
+          |         Class d = null;
+          |         if("local".equals(cl)) {
+          |             d = Class.forName(CLASS_NAME);
+          |         } else if("thread".equals(cl)) {
+          |             d = Thread.currentThread().getContextClassLoader().loadClass(CLASS_NAME);
+          |         }
+          |
+          |         Object o = d.newInstance();
+          |         Method m = o.getClass().getMethod("getMessage");
+          |         String msg = (String)m.invoke(o);
+          |
+          |         JsonObject response = new JsonObject();
+          |         response.addProperty("message", msg);
+          |         return response;
+          |     }
+          | }
+        """.stripMargin.trim,
+      Seq("example", "DynamicClass.java") ->
+        """
+          | package example;
+          |
+          | public class DynamicClass {
+          |     public String getMessage() {
+          |         return "dynamic!";
+          |     }
+          | }
+        """.stripMargin.trim))
 
   def classLoaderTest(param: String) = {
     val (out, err) = withJavaContainer { c =>


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services