Swagger-codegen: [JAVA] Support HATEOAS generics on the generated API classes.

Created on 30 Nov 2017  ·  8Comments  ·  Source: swagger-api/swagger-codegen

Description


The Spring framework provides a couple of generic classes to support the HATEOAS 'constraint' of the REST application architecture. We used SpringFox to generate the JSON definition of our service that uses the Resource and PagedResource generics provided by Spring HATEOAS. The generic references appear in the JSON file in a modified form such as: PagedResources«Resource«MyStuff»» but the JAVA client code generation flattens the generic references so that PagedResources«Resource«MyStuff»» becomes PagedResourcesResourceMyStuff.

The JAVA client must build its own logic to get the content from these flattened references instead of being able to use the mechanisms provide by the Spring Framework.

My suggestion is to add a step in the code generation (probably after the templates are applied) that turns references such as PagedResourcesResourceMyStuff back into PagedResources<Resource<MyStuff>>.

Swagger-codegen version


swagger-codegen-cli 2.2.3

Swagger declaration file content or url
Command line used for generation

java -jar swagger-codegen-cli-2.2.3.jar generate -l java --library resttemplate -i service.json -t resttemplate -o api

Steps to reproduce
  1. Setup a test folder with the swagger-codegen-cli-2.2.3.jar, service.json file, and resttemplate folder from swagger-codegen\modules\swagger-codegen\src\main\resources\Java\libraries\resttemplate
  2. Execute 'java -jar swagger-codegen-cli-2.2.3.jar generate -l java --library resttemplate -i service.json -t resttemplate -o api'
  3. View to the generated EmployeeControllerApi.java at swagger-test\api\src\main\java\io\swagger\client\api\EmployeeControllerApi.java. Note return types of ResourceEmployeeInfo that want to be Resource<EmployeeInfo> and PagedResourcesResourceEmployeeInfo that want to be PagedResources<Resource<EmployeeInfo>>.
Related issues/PRs


https://github.com/springfox/springfox/issues/746 - not really resolved

Suggest a fix/enhancement

I have forked swagger-codegen and proposed a solution at https://github.com/bzylstra/swagger-codegen/tree/hateoas_generics.

Expand Resource and PagedResources generics for Java Rest

  • add new hook to codegen config: postProcessFileContents that is invoked after the file contents are generated from the template but before they are written to the file. Default is to leave contents as found
  • for java client code generator, if the library is resttemplate and template is for the api, expand all occurrences of PagedResourcesBlah into PagedResources<Blah> and ResourceBlah into Resource<Blah>

Most helpful comment

SpringFox rendered the the generics reference as per its documentation: http://springfox.github.io/springfox/docs/current/#changing-how-generic-types-are-named
I see in the JSON file:

    "responses": {
      "200": {
        "description": "OK",
        "schema": {
          "$ref": "#/definitions/PagedResources«Resource«EmployeeInfo»»"
        }
      },

Note that I also tried tweaking the JSON file to use <> instead of «» but the output of the codegen for the JAVA client on the resttemplate library was the same:

public PagedResourcesResourceEmployeeInfo getAllEmployeesUsingGET() throws RestClientException

The desired output is:

public PagedResources<Resource<EmployeeInfo>> getAllEmployeesUsingGET() throws RestClientException

Is there a variant of the JSON file that would cause the codegen to produce the desired output? I have not found it. If there is, I will gladly take up the issue with the SpringFox team.

All 8 comments

I don't think you should use swagger/OpenAPI together with HATEOAS. Swagger is meant to describe an API that has a fixed structure whereas HATEOAS aims at dynamic interfaces with auto-discovery.

Our API has a fixed structure - the payload uses Resource and PagedResources to provide links to other resources. For example, the Employee can have have direct reports that are other employees and that can be represented as a collection of links. The API is fixed - the query always returns an Employee but the Employee can include references to other Employees.
Swagger has been an excellent fit with the exception of the limitation on generics.

To me your issue is with Springfox as the generated swagger looks wrong. Can you check your Springfox config ? Did you use their Spring-data-rest plugin ?

SpringFox rendered the the generics reference as per its documentation: http://springfox.github.io/springfox/docs/current/#changing-how-generic-types-are-named
I see in the JSON file:

    "responses": {
      "200": {
        "description": "OK",
        "schema": {
          "$ref": "#/definitions/PagedResources«Resource«EmployeeInfo»»"
        }
      },

Note that I also tried tweaking the JSON file to use <> instead of «» but the output of the codegen for the JAVA client on the resttemplate library was the same:

public PagedResourcesResourceEmployeeInfo getAllEmployeesUsingGET() throws RestClientException

The desired output is:

public PagedResources<Resource<EmployeeInfo>> getAllEmployeesUsingGET() throws RestClientException

Is there a variant of the JSON file that would cause the codegen to produce the desired output? I have not found it. If there is, I will gladly take up the issue with the SpringFox team.

Any update on this issue?

@cbornet this is a pretty standard thing nowadays with spring boot + spring fox

@bzylstra did you found a workaround?

We had forked for a time but then switched to DOTNET and it was no longer an issue.

Was this page helpful?
0 / 5 - 0 ratings