Loading…
Loading…
A deep dive into the OpenAPI Repository, which stores and retrieves generated OpenAPI specifications and the metadata required for their generation.
The OpenAPI Repository is a data access component responsible for the persistence and retrieval of OpenAPI specifications. It serves as the bridge between the database and the OpenAPI generator. Its primary role is to supply the generator with all the necessary data to construct a service version's OpenAPI specification, including service metadata, enabled operations, and a wide array of fine-grained configuration overrides.
The repository fetches data from several database tables to assemble a complete picture of a service version. This includes:
After the OpenAPI generator produces a specification, the repository is used to store the resulting artifact in the database, linking it to the specific service version.
The OpenAPI Repository interacts with the database to gather all configuration and metadata for a given service version. The OpenAPI generator calls the repository's methods to fetch this data before constructing the specification.
The process flow is as follows:
findServiceVersion to retrieve basic information about the service version, such as its name, key, and environment.findEnabledOperations to get a detailed OperationSnapshot for every enabled operation in the service version. This is the most complex query, joining s2r_operation with s2r_operation_mapping to collect dozens of configuration overrides that influence the final OpenAPI specification.findOperationFaults and findOperationHeaders. These methods retrieve WSDL-defined fault contracts and SOAP headers, respectively. This data is kept separate from the main OperationSnapshot for architectural reasons but is merged by the generator to produce accurate error responses and header definitions.upsertArtifact to save the newly created OpenAPI JSON to the s2r_openapi_artifact table. This method also updates the s2r_service_version table with the artifact's SHA256 hash and generation timestamp in a single transaction.The repository is designed to be schema-defensive. If optional data like operation faults, headers, or specific override columns are missing from the database (e.g., in older schemas), the repository returns empty collections instead of failing. This allows the OpenAPI generator to proceed with sensible defaults, ensuring backward compatibility.
flowchart TD
subgraph OpenAPI Generation Process
A[OpenAPI Generator]
end
subgraph Data Persistence
DB[(Database)]
T1[s2r_service_version]
T2[s2r_operation]
T3[s2r_operation_mapping]
T4[s2r_wsdl_operation_catalog]
T5[s2r_openapi_artifact]
DB --- T1 & T2 & T3 & T4 & T5
end
subgraph Admin API
Repo[OpenAPI Repository]
end
A -- "1. Fetch metadata" --> Repo
Repo -- "findServiceVersion, findEnabledOperations, etc." --> DB
DB -- "Snapshots, Overrides, Faults, Headers" --> Repo
Repo -- "2. Return data models" --> A
A -- "3. Generate OpenAPI JSON" --> A
A -- "4. Store artifact" --> Repo
Repo -- "upsertArtifact" --> DBThe OpenApiRepository class provides the following public methods for interacting with the database.
| Method | Description |
|---|---|
findServiceVersion(UUID serviceId, UUID versionId) | Retrieves a ServiceVersionSnapshot containing metadata for a specific service version. Returns an Optional which is empty if the version is not found. |
findEnabledOperations(UUID versionId) | Returns a List of OperationSnapshot records for all enabled operations within a service version. This is the primary source of data for OpenAPI generation. |
findOperationFaults(UUID versionId) | Retrieves a map of WSDL-defined fault contracts, keyed by SOAP operation name. Used to generate specific error response schemas. Returns an empty map if no faults are defined or the schema version is old. |
findOperationHeaders(UUID versionId) | Retrieves a map of WSDL-defined SOAP headers, keyed by SOAP operation name. Used to document the _soapHeaders sidecar object in the request body. Returns an empty map if no headers are defined or the schema version is old. |
upsertArtifact(UUID serviceId, UUID versionId, String openapiJson, String sha256, String actor, OffsetDateTime generatedAt) | Inserts or updates an OpenAPI artifact in the database. This is a transactional operation that also updates the corresponding s2r_service_version record. |
listAllArtifactKeys() | Returns a list of ArtifactKey records for all stored OpenAPI artifacts, ordered by generation time. |
findArtifact(UUID serviceId, UUID versionId) | Retrieves a specific OpenApiArtifactRecord, including the full OpenAPI JSON content. Returns an Optional which is empty if the artifact is not found. |
upsertArtifact Parameters| Name | Type | Required | Description |
|---|---|---|---|
serviceId | UUID | Yes | The ID of the service. |
versionId | UUID | Yes | The ID of the service version. |
openapiJson | String | Yes | The full JSON content of the OpenAPI specification. |
sha256 | String | Yes | The SHA-256 hash of the openapiJson content. |
actor | String | No | The identifier of the user or process that triggered the generation. Defaults to "system" if null or blank. |
generatedAt | OffsetDateTime | Yes | The timestamp when the artifact was generated. |
The repository returns data in several structured record types.
Contains high-level metadata about a specific service version.
| Field | Type | Description |
|---|---|---|
serviceId | UUID | The unique identifier for the service. |
serviceVersionId | UUID | The unique identifier for the service version. |
versionNo | int | The version number. |
serviceKey | String | A short, unique key for the service. |
serviceName | String | The human-readable name of the service. |
environment | String | The deployment environment. |
description | String | A description of the service. |
direction | String | The service direction (e.g., PUBLISH, GATEWAY). |
A comprehensive record containing all configuration for a single operation. This data directly drives how the OpenAPI specification is generated for that operation. Fields are typically either an operation-level override (a String) or a map of per-field overrides (Map<String, ...>), where the key is a SOAP XPath. If an override is not set (null), the system default is used.
| Field | Type | Description |
|---|---|---|
operationKey | String | A unique key for the operation. |
soapOperationName | String | The name of the SOAP operation from the WSDL. |
soapAction | String | The SOAPAction value. |
restMethod | String | The mapped HTTP method (e.g., POST). |
restPath | String | The mapped REST URL path. |
requestSchema | String | The JSON schema for the request body. |
responseSchema | String | The JSON schema for the response body. |
timeoutMs | int | The operation-specific timeout in milliseconds. |
retryCount | int | The operation-specific retry count. |
| Field | Type | Description |
|---|---|---|
nullHandlingRequestOverride | String | Operation-level override for handling nulls in requests. |
requestFieldNullHandling | Map<String, String> | Per-field overrides for null handling in requests, mapping SOAP XPath to a mode. |
nullHandlingResponseOverride | String | Operation-level override for handling nulls in responses. |
responseFieldNullHandling | Map<String, String> | Per-field overrides for null handling in responses, mapping SOAP XPath to a mode. |
| Field | Type | Description |
|---|---|---|
booleanHandlingOverride | String | Operation-level override for boolean representation (e.g., as-bool, as-int). |
requestFieldBooleanHandling | Map<String, String> | Per-field overrides for boolean representation in requests. |
responseFieldBooleanHandling | Map<String, String> | Per-field overrides for boolean representation in responses. |
numericHandlingOverride | String | Operation-level override for numeric representation (e.g., as-number, as-string). |
responseFieldNumericHandling | Map<String, String> | Per-field overrides for numeric representation in responses. |
integerRangeBoundsOverride | String | Operation-level override to control emission of integer range bounds (emit/omit). |
responseFieldIntegerRangeBounds | Map<String, String> | Per-field overrides for integer range bounds emission in responses. |
datetimeFormatOverride | String | Operation-level override for date/time format. |
datetimeCustomPatternOverride | String | A custom pattern string used when datetimeFormatOverride is custom. |
datetimeTimezoneOverride | String | Operation-level override for the date/time timezone. |
datetimeLocalTimezoneOverride | String | Operation-level override for the local timezone. |
datetimeNullModeOverride | String | Operation-level override for representing null date/times (omit/null). |
responseFieldDatetimeHandling | Map<String, Object> | Per-field overrides for date/time handling. Values can be a format string or a structured object with format, timezone, etc. |
durationHandlingOverride | String | Operation-level override for duration representation. |
responseFieldDurationHandling | Map<String, String> | Per-field overrides for duration representation in responses. |
binaryHandlingOverride | String | Operation-level override for binary data representation. |
responseFieldBinaryHandling | Map<String, String> | Per-field overrides for binary data representation in responses. |
| Field | Type | Description |
|---|---|---|
arrayCollapseOverride | String | Operation-level override for array handling (always-array or collapse-when-single). |
responseFieldArrayCollapse | Map<String, String> | Per-field overrides for array collapsing in responses. |
fieldCasingOverride | String | Operation-level override for JSON field casing. |
responseFieldCasing | Map<String, String> | Per-field overrides mapping a SOAP XPath to an explicit JSON field name. |
fieldOrderingOverride | String | Operation-level override for JSON field ordering. |
envelopeWrapOverride | String | Operation-level override to control response envelope wrapping. |
errorShapeOverride | String | Operation-level override for the error response shape. |
xsiTypeHandlingOverride | String | Operation-level override for xsi:type attribute handling (e.g., strip, discriminator-field). |
xsiTypeDiscriminatorFieldOverride | String | The name of the discriminator field when xsiTypeHandlingOverride is discriminator-field. Defaults to type. |
responseFieldXsiType | Map<String, String> | Per-field overrides for xsi:type handling in responses. |
headerPropagationOverride | String | Operation-level override for SOAP header propagation. |
requiredHandlingOverride | String | Operation-level override for handling required-but-empty fields (permissive or fail-with-502). |
responseFieldRequiredHandling | Map<String, String> | Per-field overrides for required field handling in responses. |
whitespaceHandlingOverride | String | Operation-level override for whitespace handling in string values (preserve, trim, collapse). |
responseFieldWhitespaceHandling | Map<String, String> | Per-field overrides for whitespace handling in responses. |
upstreamFailureStatusOverride | String | Operation-level override for upstream failure status code propagation (propagate or mask-as-200). |
requestFieldValidationRegexes | Map<String, String> | Per-field validation regexes to apply to request fields. |
responseFieldValidationRegexes | Map<String, String> | Per-field validation regexes to apply to response fields. |
NOTE
The various Map fields for per-field overrides are parsed from JSONB columns in the database. The parsing logic is robust and can handle both legacy plain string values and modern structured object values, ensuring backward compatibility.
Represents a stored OpenAPI specification artifact.
| Field | Type | Description |
|---|---|---|
id | UUID | The unique identifier for the artifact record. |
serviceId | UUID | The ID of the service this artifact belongs to. |
serviceVersionId | UUID | The ID of the service version this artifact belongs to. |
sha256 | String | The SHA-256 hash of the openapiJson content. |
generatedAt | OffsetDateTime | The timestamp when the artifact was generated. |
generatedBy | String | The user or system that generated the artifact. |
openapiJson | String | The complete OpenAPI specification as a JSON string. |
The upsertArtifact method performs a transactional database update to store a new OpenAPI specification. It executes two main SQL operations:
Upsert the Artifact: It inserts a new record into the s2r_openapi_artifact table. If a record for the service_version_id already exists, it updates the existing record with the new content. This is achieved using an ON CONFLICT clause.
insert into s2r_openapi_artifact (
id, service_id, service_version_id, openapi_json, sha256, generated_at, generated_by
)
values (?, ?, ?, ?, ?, ?, ?)
on conflict (service_version_id) do update
set service_id = excluded.service_id,
openapi_json = excluded.openapi_json,
sha256 = excluded.sha256,
generated_at = excluded.generated_at,
generated_by = excluded.generated_by
Update the Service Version: It updates the s2r_service_version table to record the sha256 and generated_at timestamp of the newly stored artifact, linking the version to its current specification.
update s2r_service_version
set openapi_sha256 = ?,
openapi_generated_at = ?
where id = ? and service_id = ?
These two operations are wrapped in a transaction to ensure data consistency.
The repository is designed with resilience to prevent failures during OpenAPI generation due to missing or malformed data.
Missing WSDL Faults/Headers: If a service version was created with an older schema that lacks the operation_faults or operation_headers columns, the findOperationFaults and findOperationHeaders methods will catch the resulting RuntimeException. They will log the error internally and return an empty Map. This allows spec generation to continue, falling back to generic error shapes and no custom headers, rather than failing completely.
Malformed JSON in Database: The helper methods (parseStringMap, parseObjectMap) that deserialize JSONB columns are wrapped in try-catch blocks. If the JSON content is null, blank, or syntactically incorrect, the method returns an empty Map or List. This isolates data corruption issues to a specific field's configuration and prevents it from halting the entire process.
Not Found Errors: Methods like findServiceVersion and findArtifact return an Optional. If the requested serviceId and versionId do not correspond to an existing record, the Optional will be empty. The calling code must handle this case and not assume a record will always be found.