openwhisk-runtime-java icon indicating copy to clipboard operation
openwhisk-runtime-java copied to clipboard

More flexibility to parsing and passing JSON input/out in Java runtime

Open csantanapr opened this issue 7 years ago • 14 comments

originally proposed by @kameshsampath

It would be great to have making OW Java Action use standard Java main method signature with just String[] args and we define custom Launcher that convert the args to JSON and delegate to OW Java Function Launcher, this way it will be easy for applications to be built and tested outside before testing in OW

@rabbah suggested the use of FDK (Function Developer Kit) to hide complexity to deal with a string from end users

On 3, did you consider an openwhisk java FDK which provides a standard wrapper instead for local development?

created out of #12

csantanapr avatar Feb 26 '18 13:02 csantanapr

Also the current return type (com.google.gson.JsonObject) of a Java action signature prevents from returning a JSON array. I think it should be com.google.gson.JsonElement instead. Of course, this is irrelevant if the parsing method is changed completely.

mkouba avatar Mar 07 '18 14:03 mkouba

@mkouba thanks for suggestion, we are working on to adhere to standard Java Signature like main(String args[]) and allow internal class like a Luncher to parse the args and give to Launcher to fire the function

kameshsampath avatar Mar 07 '18 14:03 kameshsampath

Note: Whisk actions must return json objects. If you change the signature you’ll need to box the return value into an object elsewhere.

rabbah avatar Mar 07 '18 15:03 rabbah

I'd try to avoid main(String args[]) if possible. Instead, we could allow user to specify a java.util.function.Function implementation as a main class. And then when initializing action inspect the actual type arguments and make use of com.google.gson.Gson.fromJson(JsonElement, Type) and com.google.gson.Gson.toJsonTree(Object, Type) to perform the conversion automatically. So that a user can simply write something like:

class ListRevertAction implements Function<Foo, Foo> {

        @Override
        public Foo apply(Foo input) {
            Collections.reverse(input.getValue());
            return input;
        }
    }
 
   static class Foo {

        private List<String> value;

        public List<String> getValue() {
            return value;
        }

        public void setValue(List<String> value) {
            this.value = value;
        }
    }

I can try to send a PR if you are interested ;-)

mkouba avatar Mar 07 '18 15:03 mkouba

@rabbah Why is that? Is the contract for OW actions defined somewhere?

mkouba avatar Mar 07 '18 15:03 mkouba

@mkouba - this is where it needs to be fixed further https://github.com/apache/incubator-openwhisk-runtime-java/blob/master/core/javaAction/proxy/src/main/java/openwhisk/java/action/Proxy.java

kameshsampath avatar Mar 07 '18 15:03 kameshsampath

I can try to send a PR if you are interested ;-)

you are most welcome

kameshsampath avatar Mar 07 '18 15:03 kameshsampath

@kameshsampath Yep, I've seen this code already. We can wrap the resulting array/primitive if necessary right there, e.g. {result : [...]}

mkouba avatar Mar 07 '18 15:03 mkouba

@mkouba https://github.com/apache/incubator-openwhisk/blob/master/docs/actions.md#creating-and-invoking-openwhisk-actions

The input to an action and the result of an action are a dictionary of key-value pairs, 
where the key is a string and the value a valid JSON value.

We should perhaps make that more prominent. The function signature abstractly is dictionary -> dictionary where the implementation of dictionary is language specific, e.g., JSON object for Javascript.

rabbah avatar Mar 07 '18 15:03 rabbah

@rabbah Ok, thanks.

mkouba avatar Mar 07 '18 15:03 mkouba

I'd try to avoid main(String args[]) if possible. Instead, we could allow user to specify a java.util.function.Function implementation as a main class.

@mkouba +1, I assume you also mean there is a a serializer/deserializer from Foo to JSON object?

More generally a Function<T1, T2> where T1 and T2 could be first class types. This create serdes overhead but allows for better function abstractions.

rabbah avatar Mar 07 '18 16:03 rabbah

I assume you also mean there is a a serializer/deserializer from Foo to JSON object?

This functionality is provided by Gson. So the only thing we need is to obtain input/output java.lang.reflect.Type through reflection and wrap the function call to convert the values.

mkouba avatar Mar 07 '18 16:03 mkouba

@rabbah this is similar in spirit what I’m doin in swift4 with Codable IN and Codable OUT?

csantanapr avatar Mar 07 '18 16:03 csantanapr

@rabbah @mkouba all I was trying to avoid doing via main(String[] args) is to avoid any third party deps with simple functions, I tend see @mkouba style of using Function,?> as entrypoint and use reflection then.. I am right now working with refactoring the javaAction to make it more simper and easier .. will share once its ready for you guys to comment and feedback

kameshsampath avatar Mar 07 '18 16:03 kameshsampath