smallrye-open-api icon indicating copy to clipboard operation
smallrye-open-api copied to clipboard

Generating multiple OpenAPI specs

Open migmachadopt opened this issue 1 year ago • 2 comments

Hi,

I am trying to use extensions as profiles to generate multiple OpenAPI specs. In a Quarkus application, I created 2 resources, each exposing 1 endpoint. The idea is for each resource to have a separate OpenAPI spec. What happens is that when generating the spec for one of the resources, the model of the other resource is being included in the spec of the first model (even though it is not being used in that model).

External resource:

@Path("/external/greeting")
public class ExternalResource {

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Operation(summary = "Get a greeting message", description = "Returns a greeting message")
    @APIResponses(value = {
        @APIResponse(responseCode = "200", description = "Successful, returning greeting message"),
        @APIResponse(responseCode = "500", description = "Internal server error")
    })
    @Extension(name = "x-smallrye-profile-external", value = "")
    public String greet() {
        return "{\"message\": \"Hello, World!\"}";
    }
}

Internal Resource:

@Path("/internal/greeting")
public class InternalResource {

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Operation(summary = "Get a greeting message", description = "Returns a greeting message")
    @APIResponses(value = {
        @APIResponse(responseCode = "200", description = "Successful, returning greeting message"),
        @APIResponse(responseCode = "500", description = "Internal server error")
    })
    @Extension(name = "x-smallrye-profile-internal", value = "")
    public GreetingDto greet() {
        return new GreetingDto();
    }
}

Maven plugin config:

<plugin>
    <groupId>io.smallrye</groupId>
    <artifactId>smallrye-open-api-maven-plugin</artifactId>
    <version>3.11.0</version>
    <executions>
        <execution>
            <goals>
                <goal>generate-schema</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <scanProfiles>
            <profile>external</profile>
        </scanProfiles>
        <schemaFilename>openapi-external</schemaFilename>
        <outputDirectory>${project.build.directory}/generated/openapi</outputDirectory>
        <includeDependenciesScopes>compile,provided,system,test</includeDependenciesScopes>
    </configuration>
</plugin>

The generated spec includes the GreetingDto which is not used in the ExternalResource

---
openapi: 3.0.3
info:
  title: Generated API
  version: "1.0"
paths:
  /external/greeting:
    get:
      summary: Get a greeting message
      description: Returns a greeting message
      responses:
        x-smallrye-profile-external: ""
        "200":
          description: "Successful, returning greeting message"
          content:
            application/json:
              schema:
                type: string
          x-smallrye-profile-external: ""
        "500":
          description: Internal server error
          x-smallrye-profile-external: ""
components:
  schemas:
    GreetingDto:
      type: object
      properties:
        message:
          description: Message
          type: string
          example: message

How can I ensure that unused components in this profile are not included in the final spec? Is there another way to produce separate specs based on annotations/tags? Another question is whether it is possible to remove the x-smallrye-profile-external label from the final spec.

migmachadopt avatar Jun 12 '24 17:06 migmachadopt

@migmachadopt , you can set mp.openapi.extensions.smallrye.remove-unused-schemas.enable=true to remove any schema in components that is not actually used.

Another question is whether it is possible to remove the x-smallrye-profile-external label from the final spec.

Set the extension within the @Operation annotation instead of directly on the method and it should be removed automatically.

@Operation(
  summary = "Get a greeting message", 
  description = "Returns a greeting message",
  extensions = {
    @Extension(name = "x-smallrye-profile-external", value = "")
  })

MikeEdgar avatar Jun 13 '24 17:06 MikeEdgar

@migmachadopt did you get this working the way you need? I'll go ahead and close this if I don't hear back.

MikeEdgar avatar Oct 28 '24 15:10 MikeEdgar

Closing due to no feedback. The solutions offered should address the original questions.

MikeEdgar avatar Nov 16 '24 13:11 MikeEdgar