Springdoc-openapi: HATEOAS part shows direct object instead of the thing we get

Created on 9 Dec 2019  路  5Comments  路  Source: springdoc/springdoc-openapi

Hi, currently I am using spring HATEOAS 1.0.1.RELEASE with spring-boot 2.2.1.RELEASE and springdoc-openapi-webmvc-core version 1.2.17. I saw that the project shows it support HATEOAS now but in swagger, I still see the example value show all the fields of EntityModel instead of the response we will get. Is there anything I need to config for that

Example value:

{
  "id": "string",
  "links": [
    {
      "rel": "string",
      "href": "string",
      "hreflang": "string",
      "media": "string",
      "title": "string",
      "type": "string",
      "deprecation": "string",
      "profile": "string",
      "name": "string"
    }
  ]
}

Response thing:

{
  "id": "test-id",
  "_links": {
    "self": {
      "href": "http://localhost:8374/my-path"
    }
  }
}

Most helpful comment

Hi,

As @kingtran2112 is pointing out, there is a mismatch between the generated documentation (based on EntityModel) and the actual JSON representations. If you are relying on the OpenAPI specification for customers and you are using Spring HATEOAS, this is not desirable.

I would expect links and embedded to follow the HAL specification draft (link), i.e. _links and _embedded. Furthermore, I would expect the structure within these sections to reflect the actual response representations rather than being based on the EntityModel structure.

All 5 comments

Hi,

The support has been addded based on the original issue feedback: #169
The sample value is based on the EntityModel structure.

If you expect another structure, please provide more details about how do expect this object to be mapped, and we will be happy to address it.

Hi,

As @kingtran2112 is pointing out, there is a mismatch between the generated documentation (based on EntityModel) and the actual JSON representations. If you are relying on the OpenAPI specification for customers and you are using Spring HATEOAS, this is not desirable.

I would expect links and embedded to follow the HAL specification draft (link), i.e. _links and _embedded. Furthermore, I would expect the structure within these sections to reflect the actual response representations rather than being based on the EntityModel structure.

Where are we on this?

I moved from SpringFox to openapi due to lack of HATEOAS support in SpringFox and I didn't want to use the SNAPSHOT version (which almost works). But I can't get it to work at all in openapi.

I'm using
spring-boot 2.2.6.RELEASE
springdoc-openapi 1.4.3

I have the following maven dependencies

    <dependency>
        <groupId>org.springdoc</groupId>
        <artifactId>springdoc-openapi-ui</artifactId>
        <version>${springdoc-openapi-version}</version>
    </dependency>

    <dependency>
        <groupId>org.springdoc</groupId>
        <artifactId>springdoc-openapi-hateoas</artifactId>
        <version>${springdoc-openapi-version}</version>
    </dependency>       

The following code generates the output as expected

    CaseService.createCase(theRequest);
    Link theCaseLink = 
        linkTo(methodOn(CaseController.class).getCase(null, theUniqueKey))
           .withSelfRel();
    RepresentationModel<?> theCaseRepresentation = 
        new RepresentationModel<>(theCaseLink);

    ResponseEntity<RepresentationModel<?>> theResponse = 
        new ResponseEntity<>(theCaseRepresentation, HttpStatus.CREATED); 
    return theResponse;

The response is

{
    "_links": {
        "self": {
            "href": "http://localhost:8080/cases/id/unique-key/abc"
        }
    }
}

But the documentation is completely off

{
  "_links": {
    "additionalProp1": {
      "href": "string",
      "hreflang": "string",
      "title": "string",
      "type": "string",
      "deprecation": "string",
      "profile": "string",
      "name": "string",
      "templated": true
    },
    "additionalProp2": {
      "href": "string",
      "hreflang": "string",
      "title": "string",
      "type": "string",
      "deprecation": "string",
      "profile": "string",
      "name": "string",
      "templated": true
    },
    "additionalProp3": {
      "href": "string",
      "hreflang": "string",
      "title": "string",
      "type": "string",
      "deprecation": "string",
      "profile": "string",
      "name": "string",
      "templated": true
    }
  }
}

I have no idea where prop2 and prop3 are coming from. But the link component in the schema is

Link {
hreflang | string
title | string
type | string
deprecation | string
profile | string
name | string
templated | boolean
}

What do I have to do, to get the documentation correct?

@milindrao,

The OpenAPI documentation is available on the endpoint /v3/api-docs. And this is what is generated by springdoc-openapi.
You are not reporting anything wrong about the generated OpenAPI ...

The prop2/prop3 are automatic examples generated by the swagger-ui, when examples are not filled depending on the types.
This the swagger-ui default behaviour and not a springdoc-openapi one;

If you want to change adapt the examples, you use can use OpenApiCustomiser to attach the example you want to display.

Thanks. I fixed it by doing the following.

Declare a CaseHrefRepresentation class

@SuppressWarnings("rawtypes")
@Schema (example = "{\"_links\": {\"self\": {\"href\": \"http://<domain:port>/cases/id/unique-key/case_id\"}}}")
class CaseHrefRepresentation extends RepresentationModel {}

In the method definition, use the class in the schema

@Operation(summary = "Creates and saves a case.",
           responses = { 
                @ApiResponse(responseCode = "201", description = "Created", content = @Content(schema = @Schema(implementation = CaseHrefRepresentation.class))),
                @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content),
})
@ResponseStatus(HttpStatus.CREATED)     // Needed to prevent the creation of HttpStatus.OK in swagger.
@PostMapping(value = "/cases",
             produces = {application/hal+json},
             consumes = {MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<RepresentationModel<?>> createCase(

I'm sure there's a better more correct way to do this. But for now, it works for me.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

kfirfer picture kfirfer  路  5Comments

vilmosnagy picture vilmosnagy  路  6Comments

danielbecs picture danielbecs  路  4Comments

amorenew picture amorenew  路  5Comments

Orxcle-xx picture Orxcle-xx  路  4Comments