apache / openwhisk

Apache OpenWhisk is an open source serverless cloud platform
https://openwhisk.apache.org/
Apache License 2.0
6.54k stars 1.17k forks source link

[Feature request] OpenWhisk Java Client sdk #2466

Open style95 opened 7 years ago

style95 commented 7 years ago

We need OpenWhisk java client library. It will provide features just like other libraries. (ex: javascript client sdk)

arprasto commented 7 years ago

yes it is badly needed.

misl commented 7 years ago

Using the Openwhisk swagger definition I tried to create a Java Client Library myself, details can be found here

Unfortunately Swagger code generation can not cope with properties having no type, as in:

        "KeyValue": {
            "required": [
                "key",
                "value"
            ],
            "properties": {
                "key": {
                    "type": "string"
                },
                "value": {
                    "description": "Any JSON value"
                }
            }
        }

The resulting KeyValue class only has a key and no value.

So I probably need to customize a swagger template file to achieve a usable KeyValue class.

sjfink commented 7 years ago

@misl if we just "fix" the swagger by adding types do you think the swagger-codegen will work?

bbrowning commented 7 years ago

I've looked at this a bit and I can't find a way to correctly specify the type here that works for all clients. You can specify a type of "object" that works for the Java client but fails some of the existing schema validation specs because a Swagger object is really a bit different than allowing any valid JSON type. If we upgrade to OpenAPI 3 here instead of Swagger 2 some of the new anyOf/oneOf keywords may help. Or, we could try to "fix" and/or try a newer version of swagger-codegen to see if this is an issue they've fixed.

misl commented 7 years ago

I partially agree with @bbrowning. OpenAPI 3 has extra features (anyOf / oneOf) to better specify the KeyValue structure. But the Swagger CodeGen for OpenAPI 3 has not yet been released. I don't when this will be finished.

Swagger 2 however still can be used. It is possible to customize the underlying template. Since KeyValue is the only structure with type Object in there. There will probably be no side effects.

misl commented 7 years ago

Is my custom Openwhisk Java Client I gave the following a try:

        "KeyValue": {
            "required": [
                "key",
                "value"
            ],
            "properties": {
                "key": {
                    "type": "string"
                },
                "value": {
                    "type": "object",
                    "description": "Any JSON value"
                }
            }
        },

Unfortunately every action invocation gives me a bad request. But this is due to retrofit automatically URL encoding the slash after the package name in the actionName:

  @POST("namespaces/{namespace}/actions/{actionName}")
  Call<Activation> invokeAction(
    @Path("namespace") String namespace, @Path("actionName") String actionName, @Body KeyValue payload, @Query("blocking") String blocking, @Query("result") String result, @Query("timeout") Integer timeout
  );

I see 2 possible option around this:

  1. Modify Swagger CodeGen to add encoding = false to the @Path annotation. Side effect would be that other special characters in the actionName are no longer URL encoded. (Question: are special characters allowed in package and action names?)
  2. Modify the Openwhisk URI swagger file to explicitly mention the package name and the action name in the package. Effectively changing:
    @POST("namespaces/{namespace}/actions/{actionName}")

    to

    @POST("namespaces/{namespace}/actions/{packageName}/{actionName}")

What would be the best option? Currently I favor 2.

misl commented 7 years ago

Separating packageName (see change) like mentioned in my previous comment results in a genarated openwhisk java client which allows me to invoke (no argument) actions. This time I get back a 202.

I am still investigation whether sending arguments resutls in expected behaviour.

misl commented 7 years ago

Hmm, I seem to be able to invoke an action but somehow it does not show up in my activation log :-(

I get the following response from my invocation:

Response{
    protocol=http/1.1, 
    code=202, 
    message=Accepted, 
    url=https://openwhisk.ng.bluemix.net/api/v1/namespaces/waitr_DEV/actions/traeckit.tenants/debug
}

My request looks just fine:

Request{
    method=POST, 
    url=https://openwhisk.ng.bluemix.net/api/v1/namespaces/waitr_DEV/actions/traeckit.tenants/debug, 
    tag=Request{
        method=POST, 
        url=https://openwhisk.ng.bluemix.net/api/v1/namespaces/waitr_DEV/actions/traeckit.tenants/debug, 
        tag=null
    }
    body={
        content={"key":"params","value":"hallo"}
        type=application/json; charset=UTF-8
    }
}

Anyone a clue?

rabbah commented 7 years ago

If you have an activation id, you can fetch by id. If you're using wsk activation list or using the UI, indexing the new activations may take a little bit of time.

rabbah commented 7 years ago

Note that for actions not in packages, the URL is @POST("namespaces/{namespace}/actions/{actionName}") and not this @POST("namespaces/{namespace}/actions/{packageName}/{actionName}")

misl commented 7 years ago

Made packageName optional, but still have to test.

misl commented 7 years ago

Okay I got another step further. The reason I got a 202 is because I didn't tell it to do a blocking request. I figured this out by comparing wsk -v results with my own output: wsk -v --> https://openwhisk.ng.bluemix.net/api/v1/namespaces/waitr_DEV/actions/traeckit.tenants/debug?blocking=true&result=true java api --> https://openwhisk.ng.bluemix.net/api/v1/namespaces/waitr_DEV/actions/traeckit.tenants/debug

Modifying the request:

openwhisk.actions().invokeAction( namespace, packageName, actionName, parameters, null, null, null)

into

openwhisk.actions().invokeAction( namespace, packageName, actionName, parameters, "true", "true", null)

Gave me a 200 response, yeah!

The next thing troubling me is the actual response message. The wsk based invoke gives response data that I can NOT find in my java api based invoke.

misl commented 6 years ago

The expected data was not received due to setting the result query parameter to true. According to swagger definition:

...
{
    "name": "result",
    "in": "query",
    "description": "Return only the result of a blocking activation. Default is false.",
    "required": false,
    "type": "string",
    "enum": [
        "true",
        "false"
    ]
},
...

Even though I was doing a blocking call, I still had to set it to false to get the activation details. This brought a little further, but parsing the activation/response resulted into an exception. For this to parse correctly I had to make another modification to the swagger file.

"logs": {
    "type": "array",
    "description": "Logs generated by the activation",
    "type": "string"
}

Had to become:

"logs": {
    "type": "array",
    "description": "Logs generated by the activation",
    "items": {
        "type": "string"
    }
}

Doing this in 2 different places made the response parse correctly. Looking at the response in more details it looks like there is another mismatch in the api specification. The activation.result (from the specification) is not present in the response but activation.response (unspecified) is. Below is an example response I got during testing:

"response":{  
   "result":{  
      "id":"123",
      "Name":"name"
   },
   "success":true,
   "status":"success"
}
lordofthejars commented 6 years ago

Any news about this? Any published artifacts?

bbrowning commented 6 years ago

There isn't any official Java client yet, but as a followup to updating the Swagger spec in #3878 I'm hoping we can get an autogenerated via Swagger Codegen Java client working soon.

lordofthejars commented 6 years ago

I am really expecting this, so we can start creating some integration tools for openwhisk such as maven, gradle plugins, arquillian cube integration, ....

evanchooly commented 6 years ago

I wanted to give a heads up that I’m starting work on building out a java client based on the swagger spec as part of the work we’re doing at Red Hat. The repo can be found here for now: https://github.com/projectodd/openwhisk-client-java it’s fairly bare bones at the moment but has working action invocation via the generated swagger client. Now that I have some of the pieces in place, i hope to iterate very quickly on it.

vic-cw commented 5 years ago

@evanchooly is your repo usable? It seems the Maven artifacts don't contain any jar

evanchooly commented 5 years ago

it was last I tried it. Where are you looking for jars?

https://search.maven.org/artifact/org.projectodd.openwhisk/openwhisk-client-java/0.5/pom

vic-cw commented 5 years ago

Thanks for the swift reply! I looked here: http://central.maven.org/maven2/org/projectodd/openwhisk/openwhisk-client-java/0.5/

evanchooly commented 5 years ago

looks like there are some weird warts in those poms. check here: http://central.maven.org/maven2/org/projectodd/openwhisk/client/0.5/

vic-cw commented 5 years ago

Ah, that's because that's not the same artifact name. Thanks a lot!

vic-cw commented 5 years ago

@evanchooly I started a Gradle plugin based on your Java client: https://github.com/vic-cw/openwhisk-gradle-plugin. Hope that makes you happy :)

@lordofthejars I also wanted to give you a heads up since you previously voiced the idea of such a tool.

Feel free to take a look at this first version. I would love to have your thoughts on it!

evanchooly commented 5 years ago

Hrm. Perhaps I should work on this then. :) Last I checked the openapi spec was woefully out of sync with the actual implementation, though.

vic-cw commented 5 years ago

@evanchooly I made a few pull requests on your repo, to fix some bugs and add support for some features