Closed TharmiganK closed 3 weeks ago
The lang support issue: https://github.com/ballerina-platform/ballerina-lang/issues/43041
Experienced the following issues:
Due to the above issues the design has been altered as follows:
Introspection resources:
The file will be created in the <target-dir>/resources
directory but the file generation will only happen when the HTTP code modifiers(payload annotation modifier) are executed.
Service contract type:
A service type visitor will run with OpenAPI code analyzer to get all the service contract types. If the service is implemented by a service contract in the same project then we use the information from the service type visitor to generate the OpenAPI specification. If the service is implemented by a service contract which is imported then load the OpenAPI template from the bala.
For service contract types which are public, we need to generate and pack the OpenAPI template in the bala. For this, the file should be placed in the <target-dir>/resources
directory.
Description
Current introspection and service contract type implementations uses code modifiers to add the generated OpenAPI specification to the annotation. Since we cannot ensure the order of execution for the code modifiers, it is advised to use the static resources to implement the above use cases. This static resource support will be available with Ballerina SwanLake Update 10.
Tasks
Introspection resources
Feature overview
Ballerina allows users to embed the OpenAPI specification in a service and expose it as introspection resources.
There are two ways of embedding the OpenAPI specification:
Manually providing the path in the
openapi:ServiceInfo
annotation:Auto generation using the OpenAPI tool:
When embed is set to true we add the OpenAPI specification as a
byte[]
in thehttp:ServiceConfig
annotation. This is done by a code modifier:At run-time we expose the following resources for OpenAPI introspection:
OPTIONS /socialMedia
- Returns the links for the introspection resources in the headerGET /socialMedia/openapi-doc-dygixywsw
- Returns the OpenAPI specification in JSON formatGET /socialMedia/swagger-ui-dygixywsw
- Returns an HTML response which represents the swagger view of the OpenAPI specificationThese resources are attached to the service at native level by reading the content of the
openApiDefinition
field in thehttp:ServiceConfig
annotation.Changes with static resources
Rather than adding the OpenAPI specification to the
http:ServiceConfig
using a code modifier, it should be added as a static resource in the target directory and should be read at runtime.If the OpenAPI specification is manually added via the
contract
field in theopenapi:ServiceInfo
annotation, that path should be used to read the OpenAPI specification. Otherwise the OpenAPI specification should be generated and added as a resource in the<target-dir>/resources
.The static resource creation for OpenAPI should be performed in a code analyzer.
The path to the target directory can be obtained by the Ballerina platform APIs.
The resources in the target directory should be available in the class path and use the Java resources API to load them at runtime.
When generating the OpenAPI resource file, there should be a one to one mapping between the service node and the file name. We already have a unique id for all the service declarations from ballerina-lang. This is given in the constant annotation
IntrospectionDocConfig
:The
name
field in theIntrospectionDocConfig
has the hash code of the ServiceDeclarationSymbol which is accessible via the compiler plugin. The hash code is generated with the combination of symbol name,ModuleId
and theLocation
. Since the OpenAPI generation happens at the code analyzer, it is safe to assume that there will not be any modifications to the service declaration.Service Contract Type
Feature overview
Developers can use a contract first approach to define the service type first and then they could implement that service type.
When a service is implemented via the service contract, the OpenAPI specification should be obtained from the service contract type rather than the service declaration.
To support that, the OpenAPI specification is generated for the service contract type and added in a constant annotation:
http:ServiceContractInfo
. This is done via a code modifier.With this change, whenever we try to obtain the OpenAPI specification from the service declaration which is implemented via the service contract, we generate the OpenAPI specification by incorporating the listener information from the service declaration into the existing OpenAPI specification in the service contract type. This happens at compile time.
The service contract types can be
public
and they can be implemented in a different package by importing the type. Since we are adding a constant annotation we could read this value from the semantic APIs.Changes with static resources
Rather than adding the OpenAPI specification in the
http:ServiceContractInfo
constant annotation using a code modifier, it should be added as a resource.When adding the OpenAPI specification as a resource, the following should be considered:
<target-dir>/resources
. The target directory should be obtained from the platform APIsBallerina project:
The service contract type is not
public
: The generated OpenAPI specification should be placed in the<target-dir>/resources
. The target directory should be obtained from the platform APIsThe service contract type is
public
: The generated OpenAPI specification should be placed in theresources
directory of the package. Since this public service type can be referred to in external projects, we need to pack the OpenAPI specification as a resourceThe generated OpenAPI specification should have a unique name to access at compile time.
Clean up tasks
openApiDefintion
field in thehttp:ServiceConfig
annotationRelated Issues