Loading…
Loading…
Technical reference for the OpenApiService, which generates and stores OpenAPI 3.0 specifications for PUBLISH services based on WSDL and platform
The OpenApiService is a server-side component responsible for generating, validating, and storing OpenAPI 3.0.3 specifications for API services managed by the platform. It solves the problem of creating and maintaining accurate, machine-readable REST API contracts for API consumers by automating their generation from the platform's internal service definitions.
The service primarily operates on PUBLISH direction services, which expose a REST interface to consumers. It does not generate OpenAPI for CONSUME direction services, as their consumer-facing contract is SOAP/WSDL.
Inputs:
serviceId, versionId).OpenApiRepository, including WSDL-derived schemas, REST path/method mappings, and declared SOAP faults and headers.SystemSettingRepository and PlatformSettingsProvider, which control aspects like the server URL, data type transformations, and schema structure.Outputs:
OpenApiArtifactRecord containing the generated OpenAPI specification in JSON format.OpenApiPackage) containing the specification, mapping metadata, and checksums.The service is typically invoked as an administrative action when an API publisher needs to generate or update the public contract for a service version.
IMPORTANT
The OpenApiService will throw an IllegalStateException if invoked for a service with a CONSUME direction. The platform provides a WSDL endpoint (/consume/{env}/{key}?wsdl) for consumers of these services.
The core logic resides in the generateAndStore method, which orchestrates the creation of an OpenAPI specification. The process is designed to be robust, with built-in validation and fail-soft mechanisms for non-critical steps.
flowchart TD
subgraph Generation Process
A[Start: generateAndStore] --> B{Fetch Service Version};
B --> C{Direction is 'PUBLISH'?};
C -- No (CONSUME) --> D[Throw IllegalStateException];
C -- Yes --> E{Fetch Enabled Operations};
E -- No Operations --> F[Throw IllegalArgumentException];
E -- Operations Found --> G[Fetch WSDL Faults & Headers];
G --> H[Build OpenAPI Document Map];
H --> I[Validate Conformance (enforceConformantOas30)];
I -- Invalid --> J[Throw OpenApiConformanceException];
I -- Valid --> K[Serialize Document to JSON];
K --> L[Calculate SHA-256 Hash];
L --> M[Store Artifact in Repository];
M --> N{Spec Linting Enabled?};
N -- No --> P[Return Stored Artifact];
N -- Yes --> O[lintAndStore (Fail-Soft)];
O --> P;
endserviceId and versionId and retrieves the corresponding ServiceVersionSnapshot and its list of OperationSnapshot records from the OpenApiRepository.direction. If it is CONSUME, generation is aborted with an error.soap:header blocks and wsdl:fault details associated with the service version's operations. These are used to enrich the generated specification with details about custom headers and specific error responses.Map<String, Object>). This involves building the info, servers, paths, and components sections based on the fetched metadata and system configuration.enforceConformantOas30 method performs a strict validation check on the document map. This preflight check ensures the generated spec adheres to OpenAPI 3.0 rules, preventing the storage of invalid artifacts. It detects issues such as:
type: "null" (an OpenAPI 3.1 feature).type keyword.$ref values that point to non-existent schemas in components.schemas.operationId values across all operations.openApiRepository.upsertArtifact to be stored as an OpenApiArtifactRecord.SpecLintService is configured, it is invoked to perform a quality analysis on the newly stored artifact. This process is fail-soft; any exceptions during linting are logged and swallowed, ensuring that linting failures do not prevent successful spec generation.OpenApiArtifactRecord representing the newly stored artifact.The generated document is structured according to the OpenAPI 3.0.3 specification.
info: Contains the service's name (title), version (version), and description. It also includes a custom x-i18n extension object detailing supported locales.servers: Defines the base URL for the API. The URL is constructed by combining a configured public base URL with the service's runtime path prefix: /{direction}/{environment}/{serviceKey}. See Public Base URL for resolution details.paths: Describes the available API operations. Each path item is keyed by a server-relative URL (e.g., /data/get-data). The service intelligently strips the /environment/serviceKey prefix from the full REST path to create this relative key. Each operation includes:
operationId: A unique identifier for the operation (the operationKey).summary: The soapOperationName.parameters: Path and query parameters, derived heuristically from the REST path and HTTP method.requestBody: For methods like POST and PUT, this section defines the request payload schema and provides an example. The schema may be filtered to include only fields mapped to the request body.responses: Defines possible responses, including a 200 success response, a default error response, and a specific 502 response if the WSDL defines custom fault types for the operation.components: Contains reusable components, most notably a standard ErrorResponse schema referenced by the default response in each operation.x-s2r-meta: A custom extension object containing platform-specific metadata, such as serviceId, serviceVersionId, serviceKey, and environment.x-s2r-soap: A custom extension object within each operation, detailing the underlying SOAP mapping, including operationName, soapAction, parameter bindings, and timeout/retry settings.x-s2r-rest: A custom extension object within each operation, providing REST-specific examples like a complete exampleUrl and an exampleBody.The behavior of the OpenApiService and the structure of the generated OpenAPI specification are heavily influenced by a hierarchy of configuration settings.
The base URL in the servers array is critical for API clients. Its value is resolved using the following order of precedence:
public_base_url is defined in the tenant's PlatformSettings, this value is used. This is the highest priority.public_base_url system setting stored in the database via SystemSettingRepository.S2R_PUBLIC_BASE_URL environment variable.NOTE
The service automatically strips any trailing slashes from the configured base URL to prevent double slashes when concatenating the path suffix.
Locale settings are used to generate language-specific content in examples within the specification, such as error messages.
| Setting Name (DB) | Environment Variable | Default | Description |
|---|---|---|---|
openapi.primary_locale | S2R_OPENAPI_PRIMARY_LOCALE | en-US | The primary locale for generated example content. |
openapi.supported_locales | S2R_OPENAPI_SUPPORTED_LOCALES | The primary locale | A list of all supported locales. The environment variable is a ` |
The resolution chain for these settings is: DB System Setting → Environment Variable → Hardcoded Default.
A powerful set of conversion options allows for fine-grained control over the generated schema shapes. These options are resolved on a per-operation, per-field basis using a consistent precedence chain:
response_field_null_handling).null_handling_response_override).conversion_defaults_null_handling.response).During schema generation, the resolved modes for the current operation are pinned to ThreadLocal variables. This ensures that the recursive schema-building logic correctly applies the active transformations for every field.
Key configurable transformations include:
null_handling): Controls how nillable fields are represented (e.g., as-null, as-empty-value, omit-field).boolean_handling): Determines the JSON representation of boolean values (e.g., as-bool, as-int).numeric_handling): Controls the representation of numbers (e.g., as-number, as-string).datetime_handling): Defines the format for date/time types (e.g., iso-8601-utc, epoch-millis, custom).array_collapse): Governs whether an array with a single item is "collapsed" into a scalar object.field_casing, field_ordering): Transforms property names (e.g., to camelCase, snake_case) and sorts them.envelope_wrap): Wraps the entire response body in a standard envelope (e.g., { "data": ... }).error_shape): Defines the structure of the JSON error response.xsi:type Handling (xsi_type_handling): Controls whether to strip, retain, or use xsi:type attributes for polymorphism.header_propagation): Determines how SOAP response headers are exposed to the REST consumer (e.g., drop, expose-as-http-headers).required_handling): Controls whether WSDL-required fields are marked as required in the OpenAPI schema.whitespace_handling): Adds pattern constraints to enforce whitespace trimming or collapsing on string fields.upstream_failure_status): Controls how upstream failures are represented in the HTTP response.The OpenApiService exposes the following public methods for use by other platform components.
generateAndStoreGenerates, validates, and stores an OpenAPI specification for a given service version.
public OpenApiArtifactRecord generateAndStore(UUID serviceId, UUID versionId, String actor)serviceId (UUID): The ID of the service.versionId (UUID): The ID of the service version.actor (String): Identifier for the user or process initiating the generation.OpenApiArtifactRecord containing the generated spec and its metadata.IllegalArgumentException: If the service version is not found or contains no enabled operations.IllegalStateException: If generation is attempted for a CONSUME service.OpenApiConformanceException: If the generated document fails internal OpenAPI 3.0 validation.findRetrieves a previously generated OpenApiArtifactRecord from the repository.
public Optional<OpenApiArtifactRecord> find(UUID serviceId, UUID versionId)serviceId (UUID): The ID of the service.versionId (UUID): The ID of the service version.Optional containing the OpenApiArtifactRecord if found, or an empty Optional otherwise.exportPackageGenerates and returns a ZIP package containing the OpenAPI specification and related metadata.
public OpenApiPackage exportPackage(UUID serviceId, UUID versionId)serviceId (UUID): The ID of the service.versionId (UUID): The ID of the service version.OpenApiPackage object, which is a record containing the ZIP file as a byte[], its SHA-256 hash, and its size.IllegalArgumentException: If the OpenAPI artifact for the given service version is not found.The exportPackage method produces a ZIP archive with a standardized structure. This allows for portable distribution of the API contract and its associated mapping information.
The archive contains the following files:
openapi.json: The full, generated OpenAPI 3.0.3 specification for the service version.mapping-metadata.json: A JSON file containing metadata about the SOAP-to-REST mapping for each operation. This includes the operationKey, soapOperationName, restMethod, restPath, and other runtime parameters.checksums.json: A JSON file containing the SHA-256 hashes of openapi.json and mapping-metadata.json.An example of mapping-metadata.json:
{
"serviceId": "...",
"versionId": "...",
"generatedAt": "...",
"operationCount": 1,
"operations": [
{
"operationKey": "my-op-key",
"soapOperationName": "MySoapOperation",
"soapAction": "http://example.com/MySoapOperation",
"restMethod": "POST",
"restPath": "/test/my-service/my-op",
"timeoutMs": 5000,
"retryCount": 0
}
]
}
IllegalArgumentException: service version not found or no enabled operations in service version:
serviceId or versionId does not exist, or the specified service version has no operations marked as enabled.IllegalStateException: OpenAPI generation is not applicable to CONSUME services:
CONSUME.PUBLISH services.OpenApiConformanceException:
duplicate operationId, broken $ref).OpenApiRepository: The data access layer for service, version, and operation metadata.SystemSettingRepository: The source for system-wide configuration defaults.PlatformSettingsProvider: The source for tenant-specific configuration in SaaS environments.SpecLintService: An optional collaborator for performing quality analysis on generated specs.ConversionOptionResolver: Centralized logic for resolving the effective value of a conversion option from the configuration hierarchy.