0

Firstly, it's my first time working with OpenAPI, so any comments are welcome.

My question is: OpenAPI generate an interface of my API "PriceControllerApi" that returns a ResponseEntity<PriceDto> this is the generated DTO by open API. The method that override in my class controller return a ResponseEntity<PriceDto> but this DTO is my own DTO.

What is the best practice?

  • As my service returns my DTO, make a copy of this DTO to the generated DTO and return it on the return
  • make a template for the generated API interface that returns my DTO
  • Is there any other option that is more correct?

Here is the code

api-docs.json

    {
  "components": {
    "schemas": {
      "PriceDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "ID del precio",
            "format": "int32"
          },
          "productId": {
            "type": "integer",
            "description": "ID del producto",
            "format": "int64"
          },
          "brandId": {
            "type": "integer",
            "description": "ID de la marca",
            "format": "int64"
          },
          "priceList": {
            "type": "integer",
            "description": "Orden de ofertas",
            "format": "int32"
          },
          "priority": {
            "type": "integer",
            "description": "Prioridad",
            "format": "int32"
          },
          "startDate": {
            "type": "string",
            "description": "Fecha inicio de la oferta",
            "format": "date-time"
          },
          "endDate": {
            "type": "string",
            "description": "Fecha fin de la oferta",
            "format": "date-time"
          },
          "price": {
            "description": "Precio unitario",
            "format": "double",
            "type": "number"
          },
          "curr": {
            "type": "string",
            "description": "Tipo de moneda"
          }
        },
        "description": "Objeto que representa el precio"
      }
    }
  },
  "info": {
    "title": "OpenAPI definition",
    "version": "v0"
  },
  "openapi": "3.0.1",
  "paths": {
    "/prices": {
      "get": {
        "tags": [
          "price-controller"
        ],
        "summary": "Obtener precio",
        "operationId": "getPrice",
        "parameters": [
          {
            "name": "applicationDate",
            "in": "query",
            "description": "Fecha y hora de la aplicación",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date-time",
              "example": "2023-05-31T10:30:00"
            }
          },
          {
            "name": "productId",
            "in": "query",
            "description": "Id del producto",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "brandId",
            "in": "query",
            "description": "Id de la marca",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Solicitud inválida"
          },
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PriceDto"
                }
              }
            }
          },
          "404": {
            "description": "Valor no encontrado"
          }
        }
      }
    }
  },
  "servers": [
    {
      "url": "http://localhost:8080",
      "description": "Generated server url"}]
}

plugin of pom.xml

<plugin>
                <groupId>org.openapitools</groupId>
                <artifactId>openapi-generator-maven-plugin</artifactId>
                <!-- RELEASE_VERSION -->
                <version>5.4.0</version>
                <!-- /RELEASE_VERSION -->
                <executions>
                    <execution>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                        <configuration>
                            <inputSpec>${project.basedir}/api-docs/json/api-docs.json</inputSpec>
                            <generatorName>spring</generatorName>
                            <packageName>${project.groupId}.gen</packageName>
                            <apiPackage>${project.groupId}.gen.api.v1</apiPackage>
                            <modelPackage>${project.groupId}.gen.dto</modelPackage>
                            <generateApiTests>false</generateApiTests>
                            <generateModelTests>false</generateModelTests>
                            <library>spring-boot</library>
                            <skipValidateSpec>false</skipValidateSpec>
                            <configOptions>
                                <basePackage>com.prueba.test</basePackage>
                                <reactive>false</reactive>
                                <delegatePattern>true</delegatePattern>
                                <interfaceOnly>true</interfaceOnly>
                                <sourceFolder>src/main/java</sourceFolder>
                                <!--suppress UnresolvedMavenProperty -->
                                <additionalModelTypeAnnotations>@lombok.Builder @lombok.NoArgsConstructor @lombok.AllArgsConstructor</additionalModelTypeAnnotations>
                                <useTags>true</useTags>
                            </configOptions>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

my controller with the first option a mencioned

 @Override
    public ResponseEntity<com.prueba.gen.dto.PriceDto> getPrice(OffsetDateTime applicationDate, Long productId, Long brandId){
        if (applicationDate == null || productId <= 0 || brandId <= 0) {
            return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
        }

        PriceDto priceDto = this.priceService.getByApplicationDateAndProductIdAndBrandId(applicationDate.toLocalDateTime(), productId, brandId);
        if (priceDto.getId() == 0) {
            throw new PriceNotFoundException("Price not found for application date " + applicationDate + ", product " + productId + ", brand " + brandId);
        }
       com.prueba.gen.dto.PriceDto generatedPriceDto = DtoMapper.INSTANCE.mapSourceToDestination(priceDto);
        return new ResponseEntity<>(generatedPriceDto,HttpStatus.OK);
    }

any contribution or improvement of the code is welcome. Thank you!

  • 1
    You can use mapstruct to mapper PriceDto to com.prueba.gen.dto.PriceDto – fixcer Jun 01 '23 at 08:20
  • Either use mapstruct (easiest solution) or you can map your object to be returned by openapi generator [example here](https://stackoverflow.com/questions/59072297/openapi-generator-reference-an-external-pojo-in-yaml-file-specification/59085102#59085102) – bilak Jun 01 '23 at 08:52
  • Why not return generated dto from your service? – ILya Cyclone Jun 01 '23 at 17:39

0 Answers0