OpenAPITools / OpenAPITools/openapi-generator
[BUG][spring] HATEAOS is not compatible with main openapi objective
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 26.8k
- Forks
- 7.7k
- PR merge metrics
- PR metrics pending
Description
Bug Report Checklist
- Have you provided a full/minimal spec to reproduce the issue?
- Have you validated the input using an OpenAPI validator (example)?
- Have you tested with the latest master to confirm the issue still exists?
- Have you searched for related issues/PRs?
- What's the actual output vs expected output? => Actual: Undocumented API or compilation error, Expected: Well documented API that compiles
- [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description
Main openapi objective described here: https://spec.openapis.org/oas/v3.1.0.html#abstract includes:
The OpenAPI Specification (OAS) defines a standard, programming language-agnostic interface description for HTTP APIs, which allows both humans and computers to discover and understand the capabilities of a service without requiring access to source code, additional documentation, or inspection of network traffic. [...]
But if we decide to use spring generator and opt-in hateoas things get complicated.
If we go with basic definition of API spec (simplified pet store) & config - placed below. Then we got API that compiles 🥳, but at the same time is undiscoverable 😭.
Because if we do "implement" findPetsByStatus like this return ResponseEntity.ok().body(List.of(new Pet())); then such request: curl -X GET -i 'http://localhost:8080/pet/findByStatus?status=available' returns [{"links":[],"id":null,"name":null,"category":null,"photoUrls":[],"tags":null,"status":null}].
(yeah I know this is NOT HAL representation, but probably can be changed by spring configuration)
Now we have some part of return value (links) not documented in openapi. But as we like api-first approach and generating client and server from one definition then only one option remains. Add Links to definition:
just add:
links:
$ref: '#/components/schemas/Links'
to pet properties, and components:
Link:
description: ''
type: string
Links:
description: ''
type: object
properties:
next:
$ref: '#/components/schemas/Link'
description: ''
And we will get:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.10.1:compile (default-compile) on project test: Compilation failure
[ERROR] tmp/pet/src/main/java/com/test/model/Pet.java:[237,23] getLinks() in com.test.model.Pet cannot override getLinks() in org.springframework.hateoas.RepresentationModel
[ERROR] return type @javax.validation.Valid com.test.model.Links is not compatible with org.springframework.hateoas.Links
If I understand correctly here we should be rescued by https://openapi-generator.tech/docs/usage/#type-mappings-and-import-mappings
but when we add to config:
importMappings:
Links: "org.springframework.hateoas.Links"
We ended up with API that compiles 🥳 and is discoverable 🥳. Sadly 😭now we have
public class Pet extends RepresentationModel<Pet> {
//[...]
@JsonProperty("links")
private Links links;
generated as Pet model but RepresentationModel has itself:
private final List<Link> links;
Now "builder" API of Pet mixes up with RepresentationModel API and nothing is straightforward for now on. Even worse RepresentationModel API is useless as its property (links) won't end up in JSON.
openapi-generator version
Both docker's v6.1.0 and latest (master)
OpenAPI declaration file content or url
https://gist.github.com/plblueraven/9d844001829d3548f62990cd41a24392 - basic
https://gist.github.com/plblueraven/f1e0481427ae99f980e6d96d963ce845 - with links
Generation Details
Generate server using docker run --rm -v "${PWD}/${generatedApiDirectoryRelativeLocation}:/generated-api" -v "${PWD}/${apiDefinitionFileRelativeLocation}:/spec/api.yaml" -v "${PWD}/${apiGeneratorConfigFileRelativeLocation}:/config.yaml" openapitools/openapi-generator-cli:latest generate -c /config.yaml
With such (effectively) config.yaml:
inputSpec: /spec/api.yaml
outputDir: generated-api
generatorName: spring
additionalProperties:
apiPackage: com.test
modelPackage: com.test.model
supportingFilesToGenerate: "ApiUtil.java"
groupId: com.test
artifactId: test
artifactVersion: 0.0.0
hateoas: true
or this one:
inputSpec: /spec/api.yaml
outputDir: generated-api
generatorName: spring
importMappings:
Links: "org.springframework.hateoas.Links"
additionalProperties:
apiPackage: com.test
modelPackage: com.test.model
supportingFilesToGenerate: "ApiUtil.java"
groupId: com.test
artifactId: test
artifactVersion: 0.0.0
hateoas: true
Steps to reproduce
Generate server with above config and later go to generated directory and run mvn spring-boot:run.
Related issues/PRs
#1130
Suggest a fix
Make hateoas option in spring generator compatible with main openapi objective? IMO way that it should be done needs discussion.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing both configurations with the spring generator, then compare the generated Pet.java model with Spring HATEOAS RepresentationModel and the Maven compilation output. The basic and Links OpenAPI declarations and the docker generation command provide the reproduction path. Done requires a decided compatibility approach that generates a compiling, documented API without conflicting links behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, openapi, spring
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100