Loading…
Loading…
Explains how the platform generates OpenAPI 3.0.3 specifications from WSDL and service configurations. Covers data flow, configuration, and validation.
The OpenAPI Generation Service is a component responsible for creating OpenAPI 3.0.3 specification documents for REST APIs that the platform exposes. It solves the problem of providing a modern, RESTful, and machine-readable contract for API consumers to interact with backend services that are natively based on SOAP.
The service's primary function, generateAndStore, takes a service and version identifier as input. It reads the service's configuration, its enabled operations, and the associated WSDL contract from the platform's repositories. Using this information, it constructs a complete OpenAPI document in JSON format. The generation process is highly configurable through a series of system settings that control data type transformations, null handling, response structure, and more.
Once generated, the OpenAPI document is validated for conformance to the OpenAPI 3.0.3 standard. A valid document is then stored as an OpenApiArtifactRecord, which includes the JSON content and a SHA-256 checksum. This artifact can be retrieved for use by API consumers, developer portals, and API gateway tooling.
This service is intended for PUBLISH direction services, where the platform exposes a new REST API to consumers. It is not applicable to CONSUME direction services, as their consumer-facing contract is the original SOAP WSDL.
The generation process translates a service's internal SOAP-based definition into an external, consumer-facing OpenAPI REST contract. The core logic is orchestrated by the generateAndStore method.
flowchart TD
subgraph "Generation Process"
A[Start: generateAndStore] --> B{Fetch Service Version};
B --> C{Direction is 'PUBLISH'?};
C -- No --> D[Throw Error: Not for 'CONSUME' services];
C -- Yes --> E{Operations Enabled?};
E -- No --> F[Throw Error: No enabled operations];
E -- Yes --> G[Load WSDL Faults & Headers];
G --> H[Build OpenAPI Document];
H --> I[Validate OAS 3.0 Conformance];
I -- Fails --> J[Throw Conformance Error];
I -- Passes --> K[Serialize to JSON & Hash];
K --> L[Store Artifact];
L --> M{Linting Enabled?};
M -- Yes --> N[Lint and Store Score (Non-blocking)];
N --> O[Return Stored Artifact];
M -- No --> O;
endgenerateAndStore is called with a serviceId and versionId.ServiceVersionSnapshot and a list of OperationSnapshot records from the OpenApiRepository.direction is PUBLISH. An IllegalStateException is thrown for CONSUME services, as they expose WSDL directly to consumers.IllegalArgumentException is thrown if not.wsdl:fault and soap:header definitions. These are used to generate more precise error responses and document required SOAP headers in the request body.buildDocument method assembles the OpenAPI map structure. It pins a snapshot of all effective system settings to a ThreadLocal variable at the start of the build to ensure consistency and improve performance by avoiding repeated database lookups for each operation.enforceConformantOas30. This validator checks for common violations of the OpenAPI 3.0 specification, such as the use of OAS 3.1 features (type: "null"), broken schema references, or missing/duplicate operationIds. A failure results in an OpenApiConformanceException.upsertArtifact to persist the OpenApiArtifactRecord in the repository.SpecLintService is configured, it is invoked to analyze the generated specification for quality and best practices. This process is non-blocking; any failures during linting are logged but do not interrupt or fail the generation process.OpenApiArtifactRecord is returned.The generated document adheres to the OpenAPI 3.0.3 structure and includes several key sections:
info: Contains the service title (serviceName), version (versionNo), and description. It also includes an x-i18n block detailing supported locales.servers: Defines the base URL for the API. The URL is constructed by combining a configured public base URL with a path suffix: /{direction}/{environment}/{serviceKey}.paths: Describes the individual API operations. Path keys are relative to the servers URL. For example, if the server URL is https://api.example.com/publish/test/my-service and an operation's full path is /publish/test/my-service/v1/data, the path key will be /v1/data.components: Contains reusable schemas, primarily a standard ErrorResponse schema.x-s2r-meta: A custom extension object containing metadata about the generation, such as the service ID, version ID, and the generating component (s2r-admin-api).The base URL in the servers block is resolved with the following order of precedence:
public_base_url is defined in the tenant's platform settings, this value is used. It typically corresponds to the tenant's unique subdomain.public_base_url system setting stored in the database.S2R_PUBLIC_BASE_URL environment variable.The service automatically strips any trailing slashes from the resolved base URL to prevent double slashes when concatenating path segments.
For each enabled operation, the service:
/{environment}/{serviceKey} prefix from the operation's configured restPath.get, post, etc.).operationId to the operation's unique operationKey.parameters for path and query variables based on heuristics applied to the restPath.requestBody for methods like POST and PUT, including a schema derived from the WSDL and an example payload. If the WSDL defines soap:header elements for the request, a special _soapHeaders object is added to the request body schema to document this convention.responses, including:
200 response for successful calls, with a schema and example derived from the WSDL response contract.502 response if the WSDL declares wsdl:faults for the operation. The schema for this response will be a oneOf the different fault detail types.default response for all other errors, which typically references the standard ErrorResponse component.The service recursively walks the internal contract definition (derived from the WSDL) to build JSON schemas for request and response bodies. This process is heavily influenced by a suite of conversion options, which can be configured at the system level and overridden per operation. These options allow fine-grained control over the final JSON shape.
Key transformations include:
nillable="true" elements are represented (e.g., as nullable: true, an empty value alternative, or omitted).true/false or 1/0. Numbers can be native JSON numbers or strings. Datetimes can be formatted as ISO-8601 strings, epoch timestamps, or a custom pattern.camelCase, snake_case), and their order can be made alphabetical.data object (e.g., { "data": { ... } })._meta object in the JSON body.These transformations are applied consistently during a single generation run by resolving the effective settings for each operation and pinning them to ThreadLocal variables.
The OpenApiService class exposes the following public methods for managing OpenAPI artifacts.
generateAndStoreGenerates and stores an OpenAPI specification for a given service version.
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): An identifier for the user or process initiating the generation.OpenApiArtifactRecord containing the generated spec, its checksum, and metadata.IllegalArgumentException: If the service version is not found or has no enabled operations.IllegalStateException: If generation is attempted on a CONSUME direction service.OpenApiConformanceException: If the generated document fails OpenAPI 3.0 validation.findRetrieves a previously generated OpenAPI artifact for a service version.
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 archive containing the OpenAPI specification and related metadata.
OpenApiPackage exportPackage(UUID serviceId, UUID versionId)serviceId (UUID): The ID of the service.versionId (UUID): The ID of the service version.OpenApiPackage object containing the ZIP file bytes, its SHA-256 checksum, and its size.openapi.json: The generated OpenAPI 3.0.3 specification.mapping-metadata.json: A JSON file with metadata about the service, version, and its operations, including REST-to-SOAP binding details.checksums.json: A JSON file containing the SHA-256 checksums of the other files in the package.IllegalArgumentException if the OpenAPI artifact for the specified version is not found.The behavior of the OpenAPI Generation Service is controlled by environment variables and database-backed system settings. System settings take precedence over environment variables.
| Name | Type | Source | Default | Description |
|---|---|---|---|---|
public_base_url | String | System Setting | — | The public base URL for the API platform. Used to construct the servers URL in the generated spec. |
S2R_PUBLIC_BASE_URL | String | Environment Variable | "" | Fallback for public_base_url if the system setting is not defined. |
openapi.primary_locale | String | System Setting | — | The primary locale (e.g., en-US, he-IL) used for generating example values in the spec. |
S2R_OPENAPI_PRIMARY_LOCALE | String | Environment Variable | en-US | Fallback for openapi.primary_locale. |
openapi.supported_locales | String | System Setting | — | A delimited list of all locales supported by the API. |
S2R_OPENAPI_SUPPORTED_LOCALES | String | Environment Variable | Primary locale | Fallback for openapi.supported_locales. Delimiters can be ` |
These system settings define the default behavior for data transformations during schema generation. Each can be overridden by a corresponding setting on an individual operation mapping.
| System Setting Key | Controls | Description |
|---|---|---|
conversion_defaults_null_handling | Nullable field representation | Defines how XSD nillable="true" fields are represented in JSON. Modes affect request and response schemas separately. |
conversion_defaults_required_handling | Required field enforcement | Determines if WSDL-required fields are marked as required in the OpenAPI schema. |
conversion_defaults_whitespace_handling | String whitespace handling | Controls if whitespace in strings is preserved, trimmed, or collapsed by adding a pattern to the schema. |
conversion_defaults_boolean_handling | xs:boolean representation | Defines whether xs:boolean types are represented as JSON booleans (true/false) or integers (1/0). |
conversion_defaults_numeric_handling | xs:decimal/xs:integer representation | Defines whether numeric types are represented as JSON numbers or strings (to preserve precision). |
conversion_defaults_integer_range_bounds | Integer schema bounds | Controls whether schemas for integer types include minimum and maximum constraints based on the type's natural range (e.g., int32). |
conversion_defaults_datetime_handling | xs:dateTime representation | Controls the format of date/time values (e.g., iso-8601-utc, epoch-millis, custom), timezone handling, and null representation. |
conversion_defaults_duration_handling | xs:duration representation | Defines how xs:duration types are represented (e.g., ISO 8601 string, total seconds as an integer). |
conversion_defaults_binary_handling | xs:base64Binary representation | Defines how binary data is represented (e.g., base64 string, data URL). |
conversion_defaults_array_collapse | Array-of-one handling | Determines if an array containing a single element should be "collapsed" into just that element. |
conversion_defaults_field_casing | Object property key casing | Defines the casing convention for JSON object keys (e.g., camelCase, snake_case, as-source). |
conversion_defaults_field_ordering | Object property key order | Defines the sort order for JSON object keys (e.g., as-schema, alphabetical). |
conversion_defaults_envelope_wrap | Response body structure | Controls whether the response payload is wrapped in an envelope object (e.g., { "data": ... }). |
conversion_defaults_error_shape | Error response structure | Defines the JSON structure for error responses. |
conversion_defaults_upstream_failure_status | Upstream failure handling | Controls how upstream SOAP faults are represented at the HTTP layer (e.g., propagating the status or masking as HTTP 200). |
conversion_defaults_xsi_type_handling | Polymorphic type (xsi:type) handling | Controls how xsi:type attributes for polymorphic elements are represented in the JSON payload. |
conversion_defaults_header_propagation | SOAP header handling | Defines how SOAP response headers are propagated to the REST consumer (e.g., dropped, as HTTP headers, in a _meta object). |
conversion_defaults_string_without_regex | Unconstrained string validation | Defines a policy for applying a default pattern to string fields that lack an explicit XSD pattern. |
The generateAndStore method can fail with the following exceptions:
IllegalArgumentException:
"service version not found": The serviceId or versionId provided does not correspond to an existing service version. Verify the identifiers are correct."no enabled operations in service version": The specified service version exists but contains no operations that are enabled for exposure. Enable at least one operation in the service configuration.IllegalStateException:
"OpenAPI generation is not applicable to CONSUME services...": An attempt was made to generate a spec for a service with direction set to CONSUME. This is not supported. This feature is only for PUBLISH services.OpenApiConformanceException:
The enforceConformantOas30 check will throw an OpenApiConformanceException if it detects any of the following issues:
type: "null" or an array for the type keyword (e.g., type: ["string", "null"]). The correct OAS 3.0 representation is type: "string" with nullable: true.$ref that points to a schema in #/components/schemas/ that does not exist. This usually indicates an issue in the internal contract generation.operationId: Every operation in the paths object must have a unique operationId.The service logs warnings for conditions that do not block generation but may indicate a configuration issue or unexpected state:
S2R-ADM-1517: Logged when a response schema for an operation is missing or empty. The service falls back to a generic success example, but the generated schema will not be representative of the actual response. This suggests an incomplete WSDL or contract import.SpecLintService are logged and swallowed, ensuring that spec generation and activation are never blocked by a quality check.