Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OpenAPI spec generation is not supported for HTTP service declarations which are defined using service object-types #6615

Closed
ayeshLK opened this issue Jun 7, 2024 · 4 comments
Assignees

Comments

@ayeshLK
Copy link
Member

ayeshLK commented Jun 7, 2024

Description:

$subject

Related to proposal: #6378

@TharmiganK
Copy link
Contributor

TharmiganK commented Jun 7, 2024

With the above proposal, openapi-tool generates the following service type with all the HTTP annotation details:

@http:ServiceContractConfig {
    basePath: "/socialMedia"
}
@http:ServiceConfig {
    auth: [
        {
            fileUserStoreConfig: {},
            scopes: ["admin"]
        }
    ]
}
public type Service service object {
    *http:ServiceContract;
    @http:ResourceConfig {
        name: "users"
    }
    resource function get users() returns socialMedia:User[]|error;

    @http:ResourceConfig {
        name: "user",
        linkedTo: [
            {name: "user", method: http:DELETE, relation: "delete-user"},
            {name: "posts", method: http:POST, relation: "create-posts"},
            {name: "posts", method: http:GET, relation: "get-posts"}
        ]
    }
    resource function get users/[int id]() returns @http:Payload {mediaType: "application/org+json"} socialMedia:User|socialMedia:UserNotFound|error;

    @http:ResourceConfig {
        name: "users",
        linkedTo: [
            {name: "user", method: http:GET, relation: "get-user"},
            {name: "user", method: http:DELETE, relation: "delete-user"},
            {name: "posts", method: http:POST, relation: "create-posts"},
            {name: "posts", method: http:GET, relation: "get-posts"}
        ]
    }
    resource function post users(socialMedia:NewUser newUser) returns http:Created|error;

    @http:ResourceConfig {
        name: "user"
    }
    resource function delete users/[int id]() returns http:NoContent|error;

    @http:ResourceConfig {
        name: "posts"
    }
    resource function get users/[int id]/posts() returns socialMedia:PostWithMeta[]|socialMedia:UserNotFound|error;

    @http:ResourceConfig {
        name: "posts",
        linkedTo: [
            {name: "posts", method: http:POST, relation: "create-posts"}
        ]
    }
    resource function post users/[int id]/posts(socialMedia:NewPost newPost) returns http:Created|socialMedia:UserNotFound|socialMedia:PostForbidden|error;
};

The implementation will look like this: (The service type is imported via a separate package, the service type can be in the same package as well)

service socialMedia:Service "/social-media" on new http:Listener(8080) {

    resource function get users() returns socialMedia:User[]|error {
        return [];
    }

    resource function get users/[int id]() returns socialMedia:User|socialMedia:UserNotFound|error {
        return {id: 1, name: "John Doe", email: "johndoe@gmail.com"};
    }

    resource function post users(socialMedia:NewUser newUser) returns http:Created|error {
        return http:CREATED;
    }

    resource function delete users/[int id]() returns http:NoContent|error {
        return http:NO_CONTENT;
    }

    resource function get users/[int id]/posts() returns socialMedia:PostWithMeta[]|socialMedia:UserNotFound|error {
        return [];
    }

    resource function post users/[int id]/posts(socialMedia:NewPost newPost) returns http:Created|socialMedia:UserNotFound|socialMedia:PostForbidden|error {
        return http:CREATED;
    }
}

In the above service declaration,

  1. None of the HTTP annotations are allowed, all of them are inferred from the service type
  2. Additional resources which are not defined in the service type, are not allowed

So for this service declaration, the openapi should be generated from the service type rather than the service declaration. Please note that the service type is a subtype of http:ServiceContract, this makes sure that the normal service types are not going to break with the changes. So, we should only generate the OAS from the service type which is a subtypes of http:ServiceContract

@TharmiganK
Copy link
Contributor

The HTTP related changes are WIP in this branch: https://github.com/ballerina-platform/module-ballerina-http/tree/service-type-support
You can use this timestamped version for testing: 2.11.1-20240607-135600-e67eb21

@ayeshLK ayeshLK removed their assignment Jun 7, 2024
@ayeshLK ayeshLK changed the title OpenAPI spec generation is not supports for HTTP service declarations which are defined using service object-types OpenAPI spec generation is not supported for HTTP service declarations which are defined using service object-types Jun 12, 2024
@TharmiganK
Copy link
Contributor

The current open-api spec generation is using the compiler syntax tree. But when we use a service contract type, we cannot access the syntax tree if the service type is outside the package (having service type in a separate package is a use case).

Even though we implement a generator using the semantic model, it is not possible for get the values of annotations using the existing APIs since the annotations are not constant.

If we consider the idea behind the service contract, then we actually know the open-api spec from the type itself. So, the open-api tool should be able to generate a spec from the service type as well(This is a non-goal of the proposal). If that is possible, we can actually generate and embed the open-api spec into the service contract type and whenever we need a open-api spec from the service implementation using a service contract type, we should be able to get it directly from the type.

This approach has two major issues:

  1. The open-api spec generation should be done by the http compiler plugin (This should ideally fix this issue as well: The OpenAPI introspection resource returns an incorrect specification  #6511)
  2. If we add the open-api spec to the annotation, we cannot access it from the semantic model unless the annotation is constant

@TharmiganK TharmiganK self-assigned this Jun 17, 2024
@TharmiganK
Copy link
Contributor

We are planning to utilise the static resources rather than constant annotations. We need APIs to read and write the resources at compile time, this issue has been tracked via ballerina-platform/ballerina-lang#43041

@TharmiganK TharmiganK added the Reason/MultipleComponentInteraction Issue occured due to interactions in multiple components. label Aug 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Archived in project
Status: Done
Development

No branches or pull requests

2 participants