# Kogito Codegen OpenApi

Module to generate OpenApi client code based on
the [OpenApi Generator Tool](https://github.com/OpenAPITools/openapi-generator/).

Taking a Serverless Workflow file as example:

```json
{
  "functions": [
    {
      "name": "countryInfoFunction",
      "operation": "restcountries.json#getByName1"
    }
  ]
}
```

In this `function` definition, we can see an operation pointing to `restcountries.json`, which is an OpenApi spec file
defined in the user's classpath:

```
src
├── main
│   └── resources
│       ├── restcountries.json

```

We support `classpath:`, `file:` and `http|s` resources. The `#getName1` portion of the operation identifies the REST
endpoint we want to call:

```json
{
  "/v2/name/{name}": {
    "get": {
      "operationId": "getByName_1",
      "parameters": [
        {
          "name": "name",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        },
        {
          "name": "fullText",
          "in": "query",
          "schema": {
            "type": "boolean"
          }
        },
        {
          "name": "fields",
          "in": "query",
          "schema": {
            "type": "string"
          }
        }
      ]
    }
  }
}
```

All the parameters are also processed by our engine, resulting in a method like this:

```java
public JsonNode getByName1(JsonNode var1,JsonNode var2,JsonNode var3)throws ApiException 
```

This class is generated by the OpenApi generator tool and post-processed by our engine.

The function call in the Serverless Workflow (SW) file looks like this:

```json
{
  "name": "GetCountryInfo",
  "type": "operation",
  "start": true,
  "actionMode": "sequential",
  "actions": [
    {
      "name": "getCountryInfo",
      "functionRef": {
        "refName": "countryInfoFunction",
        "parameters": {
          "name": "$.name"
        }
      }
    }
  ],
  "transition": {
    "nextState": "ClassifyByPopulation"
  }
}
```

If a parameter is required, the generator will fail with a specific exception for the user to fix.

Every parameter and return object is a JsonNode. This is because the SW engine treats everything as JSON. This can be
changed in the future to adapt to other scenarios, like a jBPM Service Task, each in/out parameter can be a POJO, which
is also generated by the tool.

A spec file contains the information about the server, which we can call, for example:

```json
{
  "openapi": "3.0.1",
  "info": {
    "title": "REST Countries",
    "description": "REST Countries",
    "termsOfService": "https://restcountries.eu/",
    "license": {
      "name": "Mozilla Public License MPL 2.0",
      "url": "https://www.mozilla.org/en-US/MPL/2.0/"
    },
    "version": "2.0.5"
  },
  "servers": [
    {
      "url": "https://restcountries.eu/rest/"
    }
  ]
}
```

If not provided, the tool defaults to `http://localhost`. A user can change this property in runtime via a Kogito
property in their `application.properties` file, for example:

```properties
org.kogito.openapi.client.multiplication.base_path=http://localhost:8282
```

`multiplication` is the name of the spec file defined in the Kogito resource file.

If the spec defines security objects, one can also configure username, password, and API Keys via properties. This
scenario can work now, but it would take much more time to cover everything, so I left this use case to another JIRA.

## Key Takeaways

1. Since the code generated by this module can be a requirement for other resources (such as processes), it MUST
   generate its files first.
2. This generator is a wrapper for the
   original [OpenApi Generator Tool](https://github.com/OpenAPITools/openapi-generator/). We used this tool to avoid
   reinventing the wheel. Their community is huge, active, and licensed under Apache v2.
3. The generated code is acting like a "Service" class to make REST calls. We also filter the code generated by the tool
   to adjust to our requirements and work on SpringBoot, Quarkus, and Native scenarios. You can see the examples
   here: https://github.com/kiegroup/kogito-examples/pull/591
4. All the files generated by the original tool are deleted after processed. We only keep the files that a user would
   require for their application. The generated files are then embedded in the final application inside
   the `org.kie.kogito.app.openapi`
   package. An SW file can have multiple OpenApi spec definitions.
5. The Service Task Java implementation is now being manually crafted by the Java Parser library, which is not ideal.
   See [KOGITO-4599](https://issues.redhat.com/browse/KOGITO-4599).
6. The `jbpm-serverless-workflow` module will be refactored to be a "translator" from an SW definition to a jBPM process
   only. Any generated code will be migrated to `kogito-modules-process` instead
   (and we will leverage the template files). See [KOGITO-4600](https://issues.redhat.com/browse/KOGITO-4600)
7. The `kogito-workitems` module will also be refactored. Ideally, it should be added on-demand via an extension, not
   manually added in the user's pom file.
8. The OpenApi generator tool generates REST client code based on resteasy client. It was the middle-ground solution
   we've found to generate code for SB, Quarkus, and Native. It's the same code, same post-processing. Although OpenApi
   generator tool also supports SB HTTP Client, the easiest approach was to generate the same code to avoid maintenance.
