Quarkus - OpenAPI Generator - Client

This extension is for REST code generation for client side only. If you’re looking for code generation for the server side, please take a look at the Quarkus OpenAPI Generator Server Extension.

Want to contribute? Great! We try to make it easy, and all contributions, even the smaller ones, are more than welcome. This includes bug reports, fixes, documentation, examples…​ But first, read this page.

Getting Started

Add the following dependency to your project’s pom.xml file:

Version 2.x.x of this extension supports Quarkus 3, and version 1.x.x supports Quarkus 2. We strongly recommend you to use version 2.x.x. No updates are planned for version 1.x.x.
<dependency>
  <groupId>io.quarkiverse.openapi.generator</groupId>
  <artifactId>quarkus-openapi-generator</artifactId>
  <version>3.0.0-SNAPSHOT</version>
</dependency>

You will also need to add or update the quarkus-maven-plugin configuration with the following:

You probably already have this configuration if you created your application with Code Quarkus. That said, double-check your configuration not to add another plugin entry.
<plugin>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-maven-plugin</artifactId>
  <extensions>true</extensions>
  <executions>
    <execution>
      <goals>
        <goal>build</goal>
        <goal>generate-code</goal>
        <goal>generate-code-tests</goal>
      </goals>
    </execution>
  </executions>
</plugin>

Now, create the directory openapi under your src/main/ path and add the OpenAPI spec files there. We support JSON, YAML and YML extensions.

If you want to change the directory where OpenAPI files must be found, use the property quarkus.openapi-generator.codegen.input-base-dir. IMPORTANT: it is relative to the project base directory. For example, if you have a project called MyJavaProject and decide to place them in MyJavaProject/openapi-definitions, use the following property:

quarkus.openapi-generator.codegen.input-base-dir=openapi-definitions

If you want to change the directory where template files must be found, use the property quarkus.openapi-generator.codegen.template-base-dir. If not set the templates will be expected in the build directory under classes/templates IMPORTANT: it is relative to src/main. For example, if you want your custom templates in src/main/resources/custom-templates, use the following property:

quarkus.openapi-generator.codegen.template-base-dir=resources/custom-templates

To fine tune the configuration for each spec file, add the following entry to your properties file. In this example, our spec file is in src/main/openapi/petstore.json:

quarkus.openapi-generator.codegen.spec.petstore_json.additional-model-type-annotations=@org.test.Foo;@org.test.Bar

If you want to change the base package in which the classes are generated, use the quarkus.openapi-generator.codegen.spec.<filename>.base-package property. If a base package is not provided, it will default to org.openapi.quarkus.<filename>. For example, org.openapi.quarkus.petstore_json.

quarkus.openapi-generator.codegen.spec.petstore_json.base-package=org.acme

Configuring additional-model-type-annotations will add all annotations to the generated model files (extra details can be found in OpenApi Generator Doc).

You can customize the name of generated classes. To do that, you must define the following properties:

quarkus.openapi-generator.codegen.spec.petstore_json.api-name-suffix=CustomApiSuffix
quarkus.openapi-generator.codegen.spec.petstore_json.model-name-suffix=CustomModelSuffix
quarkus.openapi-generator.codegen.spec.petstore_json.model-name-prefix=CustomModelPrefix

You can remove operationId prefix (e.g. User_findAll⇒ findAll). To do that, you must define the following properties:

quarkus.openapi-generator.codegen.spec.petstore_json.remove-operation-id-prefix=true

Character to use as a delimiter for the prefix. Default is '_'.You can define the prefix delimiter (e.g. User.findAll⇒ findAll):

quarkus.openapi-generator.codegen.spec.petstore_json.remove-operation-id-prefix-delimiter=.

You can define count of delimiter for the prefix (e.g. org.acme.UserResource.findAll⇒ findAll). Use -1 for last Default:

quarkus.openapi-generator.codegen.spec.petstore_json.remove-operation-id-prefix-count=3

The same way you can add any additional annotations to the generated api files with additional-api-type-annotations. Given you want to include Foo and Bar annotations, you must define additional-api-type-annotations as:

quarkus.openapi-generator.codegen.spec.petstore_json.additional-api-type-annotations=@org.test.Foo;@org.test.Bar
Note that the file name`petstore_json`is used to configure the specific information for each spec. We follow the Environment Variables Mapping Rules from Microprofile Configuration to sanitize the OpenAPI spec filename. Any non-alphabetic characters are replaced by an underscore _.

Run mvn compile to generate your classes in target/generated-sources/open-api-json path:

- org.acme.openapi
  - api
    - PetApi.java
    - StoreApi.java
    - UserApi.java
  - model
    - Address.java
    - Category.java
    - Customer.java
    - ModelApiResponse.java
    - Order.java
    - Pet.java
    - Tag.java
    - User.java

You can reference the generated code in your project, for example:

import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;

import org.acme.openapi.api.PetApi;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import org.jboss.resteasy.annotations.jaxrs.PathParam;

@Produces(MediaType.APPLICATION_JSON)
@Path("/petstore")
public class PetResource {

    @RestClient
    @Inject
    PetApi petApi;
}

See the integration-tests module for more information of how to use this extension. Please be advised that the extension is on experimental, early development stage.

RESTEasy Reactive and Classic support

You can use the quarkus-openapi-generator with REST Client Classic or REST Client Reactive respectively. To do so add either the classic or reactive jackson dependency to your project’s pom.xml file:

RESTEasy Classic

<dependency>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-rest-client-jackson</artifactId>
</dependency>
After Version 1.2.1 / 2.1.1 you need to declare the above dependency explicitly! Even if you stay with the REST Client Classic implementation!

RESTEasy Reactive

<dependency>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-rest-client-reactive-jackson</artifactId>
</dependency>

To make truly non-blocking calls, you need to also set the mutiny option to true. This will wrap all API return types in a io.smallrye.mutiny.Uni.

quarkus.openapi-generator.codegen.spec.my_openapi_yaml.mutiny=true

Configuring Return jakarta.ws.rs.core.Response

quarkus.openapi-generator.codegen.spec.my_openapi_yaml.mutiny.return-response=true

This will configure all API calls to return Uni<jakarta.ws.rs.core.Response>.

Configuring Return Types for Specific Operations

In cases where you need more granular control over the return types of specific OpenAPI operations, you can configure individual operations to return either a Uni or a Multi. By default, when mutiny=true is enabled, all API methods will return a Uni. However, if you have operations that should return multiple items reactively, you can specify either Multi or Uni for those operations.

To achieve this, use the mutiny.operation-ids configuration to set the return type for each operation by its operationId as defined in the OpenAPI specification.

For example:

# Enable Mutiny support for all operations
quarkus.openapi-generator.codegen.spec.my_openapi_yaml.mutiny=true

# Configure return type for specific operation IDs
quarkus.openapi-generator.codegen.spec.my_openapi_yaml.mutiny.operation-ids.addPet=Uni
quarkus.openapi-generator.codegen.spec.my_openapi_yaml.mutiny.operation-ids.updatePet=Multi

In this example:

  • The addPet operation will return a Uni.

  • The updatePet operation will return a Multi.

This allows fine-grained control over which operations are expected to return a single result (Uni) and which should handle streams of results (Multi).

If an incorrect or unsupported return type is specified for an mutiny.operation-ids, the generator will fallback to returning a Uni by default. Ensure that the return type for each operation is either Uni or Multi to avoid unintended behavior.

When using RESTEasy Reactive:

  • The client must not declare multiple MIME-TYPES with @Consumes

  • You might need to implement a ParamConverter for each complex type

Returning Response objects

By default, this extension generates the methods according to their returning models based on the OpenAPI specification Schema Object. If no response model is defined, jakarta.ws.rs.core.Response is returned.

If you want to return jakarta.ws.rs.core.Response in all cases instead, you can set the return-response property to true.

Example

Given you want to return jakarta.ws.rs.core.Response for the my-openapi.yaml file, you must add the following to your application.properties file:

quarkus.openapi-generator.codegen.spec.my_openapi_yaml.return-response=true

Logging

Since the most part of this extension work is in the generate-code execution phase of the Quarkus Maven’s plugin, the log configuration must be set in the Maven context. When building your project, add -Dorg.slf4j.simpleLogger.log.org.openapitools=off to the mvn command to reduce the internal generator noise. For example:

mvn clean install -Dorg.slf4j.simpleLogger.log.org.openapitools=off

For more information, see the Maven Logging Configuration and Maven Configuration guides.

Filtering OpenAPI Specification Files

By default, the extension will process every OpenAPI specification file in the given path. To limit code generation to only a specific set of OpenAPI specification files, you can set the quarkus.openapi-generator.codegen.include property.

For instance, if you want to limit code generation for include-openapi.yaml and include-openapi-2.yaml files, you need to define the property like:

quarkus.openapi-generator.codegen.include=include-openapi.yaml,include-openapi-2.yaml

If you prefer to specify which files you want to skip, you can set the quarkus.openapi-generator.codegen.exclude property. For instance, if you want to skip code generation for exclude-openapi.yaml and exclude-openapi-2.yaml files, you need to define the property like:

quarkus.openapi-generator.codegen.exclude=exclude-openapi.yaml,exclude-openapi-2.yaml
exclude supersedes include, meaning that if a file is in both property it will NOT be analysed.

See the module integration-tests/ignore for an example of how to use this feature.

Authentication Support

If your OpenAPI specification file has securitySchemes definitions, the inner generator will register ClientRequestFilter providers for you to implement the given authentication mechanism.

To provide the credentials for your application, you can use the Quarkus configuration support. The configuration key is composed using this pattern: quarkus.openapi-generator.[filename].auth.[security_scheme_name].[auth_property_name]. Where:

  • filename is the sanitized name of file containing the OpenAPI spec, for example petstore_json.

  • security_scheme_name is the sanitized name of the security scheme object definition in the OpenAPI file. Given the following excerpt, we have api_key and basic_auth security schemes:

{
  "securitySchemes": {
    "api_key": {
      "type": "apiKey",
      "name": "api_key",
      "in": "header"
    },
    "basic_auth": {
      "type": "http",
      "scheme": "basic"
    }
  }
}
Note that the securityScheme name used to configure the specific information for each spec is sanitized using the same rules as for the file names.
  • auth_property_name varies depending on the authentication provider. For example, for Basic Authentication we have username and password. See the following sections for more details.

Tip: on production environments you will likely to use HashiCorp Vault or Kubernetes Secrets to provide this information for your application.

If the OpenAPI specification file has securitySchemes definitions, but no Security Requirement Object definitions, the generator can be configured to create these by default. In this case, for all operations without a security requirement the default one will be created. Note that the property value needs to match the name of a security scheme object definition, eg. api_key or basic_auth in the securitySchemes list above.

Description Property Key Example

Create security for the referenced security scheme

quarkus.openapi-generator.codegen.default-security-scheme

quarkus.openapi-generator.codegen.default-security-scheme=api_key

See the module security for an example of how to use this feature.

Basic HTTP Authentication

For Basic HTTP Authentication, these are the supported configurations:

Description Property Key Example

Username credentials

quarkus.openapi-generator.[filename].auth.[security_scheme_name].username

quarkus.openapi-generator.petstore_json.auth.basic_auth.username

Password credentials

quarkus.openapi-generator.[filename].auth.[security_scheme_name].password

quarkus.openapi-generator.petstore_json.auth.basic_auth-password

Bearer Token Authentication

Authentication, these are the supported configurations:

Description Property Key Example

Bearer Token

quarkus.openapi-generator.[filename].auth.[security_scheme_name].bearer-token

quarkus.openapi-generator.petstore_json.auth.bearer.bearer-token

API Key Authentication

Similarly to bearer token, the API Key Authentication also has the token entry key property:

Description Property Key Example

API Key

quarkus.openapi-generator.[filename].auth.[security_scheme_name].api-key

quarkus.openapi-generator.petstore_json.auth.api_key.api-key

The API Key scheme has an additional property that requires where to add the API key in the request token: header, cookie or query. The inner provider takes care of that for you.

OAuth2 Authentication

The extension will generate a ClientRequestFilter capable to add OAuth2 authentication capabilities to the OpenAPI operations that require it. This means that you can use the Quarkus OIDC Extension configuration to define your authentication flow.

The generated code creates a named OidcClient for each Security Scheme listed in the OpenAPI specification files. For example, given the following excerpt:

{
  "securitySchemes": {
    "petstore_auth": {
      "type": "oauth2",
      "flows": {
        "implicit": {
          "authorizationUrl": "https://petstore3.swagger.io/oauth/authorize",
          "scopes": {
            "write:pets": "modify pets in your account",
            "read:pets": "read your pets"
          }
        }
      }
    }
  }
}

You can configure this OidcClient as:

quarkus.oidc-client.petstore_auth.auth-server-url=https://petstore3.swagger.io/oauth/authorize
quarkus.oidc-client.petstore_auth.discovery-enabled=false
quarkus.oidc-client.petstore_auth.token-path=/tokens
quarkus.oidc-client.petstore_auth.credentials.secret=secret
quarkus.oidc-client.petstore_auth.grant.type=password
quarkus.oidc-client.petstore_auth.grant-options.password.username=alice
quarkus.oidc-client.petstore_auth.grant-options.password.password=alice
quarkus.oidc-client.petstore_auth.client-id=petstore-app

The configuration suffix quarkus.oidc-client.petstore_auth is exclusive for the schema defined in the specification file and the schemaName is sanitized by applying the rules described above.

For this to work you must add Quarkus OIDC Client Filter Extension to your project.

From version 2.7.0 and onwards you must also add the quarkus-openapi-generator-oidc additional dependency. Please see the details below.

RESTEasy Classic:

<dependency>
  <groupId>io.quarkiverse.openapi.generator</groupId>
  <artifactId>quarkus-openapi-generator-oidc</artifactId>
</dependency>
<dependency>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-oidc-client-filter</artifactId>
</dependency>

RESTEasy Reactive:

<dependency>
  <groupId>io.quarkiverse.openapi.generator</groupId>
  <artifactId>quarkus-openapi-generator-oidc</artifactId>
</dependency>
<dependency>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-oidc-client-reactive-filter</artifactId>
</dependency>

If authentication support doesn’t suit your needs you can decide to disable it with enable-security-generation=false. In such case CompositeAuthenticationProvider and AuthenticationPropagationHeadersFactory wont be generated and used with your api. The option can be set globally with quarkus.openapi-generator.codegen.enable-security-generation or per api quarkus.openapi-generator.codegen.spec.my_spec_yml.enable-security-generation Custom authentication provider can be used with additional-api-type-annotations

See the module generation-tests for an example of how to use this feature.

Authorization Token Propagation

The authorization token propagation can be used with OpenApi operations secured with a security scheme of type "oauth2" or "bearer". When configured, you can propagate the authorization tokens passed to your service and the invocations to the REST clients generated by the quarkus-openapi-generator.

Let’s see how it works by following a simple example:

Imagine that we have a updatePet operation defined in the petstore.json specification file and secured with the petstore_auth security scheme. The code below shows a simple example of the usage of this operation in a user-programmed service.

import org.acme.api.PetApi;
import org.acme.model.Pet;
import org.eclipse.microprofile.rest.client.inject.RestClient;

/**
 * User programmed service.
 */
@Path("/petstore")
public class PetResource {

  /**
   * Inject the rest client generated by the quarkus-openapi-generator.
   */
  @Inject
  @RestClient
  PetApi petApi;

  /**
   * User programmed operation.
   */
  @Path("/pet/{id}")
  @PATCH
  @Produces(MediaType.APPLICATION_JSON)
  @Consumes(MediaType.APPLICATION_JSON)
  public Response customUpdatePet(@PathParam("id") long id, PetData petData) {

    // Create a new instance of the Pet class generated by the quarkus-openapi-generator and
    // populate accordingly.
    Pet pet = new Pet();
    pet.setId(id);
    applyDataToPet(pet, petData);

    // Execute the rest call using the generated client.
    // The petstore.json open api spec stays that the "updatePet" operation is secured with the
    // security scheme "petstore_auth".
    petApi.updatePet(pet);

    // Do other required things and finally return something.
    return Response.ok().build();
  }

  public static class PetData {
    // Represents the Pet modifiable data sent to the user programmed service.
  }

  private void applyDataToPet(Pet pet, PetData petData) {
    // Set the corresponding values to the Pet instance.
  }
}

Let’s see what happens when the PetResource service customUpdatePet operation is invoked by a third party.

Default flow

  1. The customUpdatePet operation is invoked.

  2. An authorization token is obtained using the corresponding petstore_auth OidcClient configuration. (for more information see OAuth2 Authentication)

  3. The authorization token is automatically passed along the PetApi updatePet operation execution using an automatically generated request filter, etc.

Propagation flow

However, there are scenarios where we want to propagate the authorization token that was initially passed to the PetResource service when the customUpdatePet operation was invoked instead of having to obtain it by using the OidcClient.

  1. The user service customUpdatePet operation is invoked, and an authorization token is passed by the third party typically by using the HTTP Authorization header.

  2. The incoming authorization token is automatically passed along the PetApi updatePet operation execution according to the user-provided configuration.

When configured, the token propagation applies to all the operations secured with the same securityScheme in the same specification file.

Propagation flow configuration

The token propagation can be used with type "oauth2" or "bearer" security schemes. Finally, considering that a given security scheme might be configured on a set of operations in the same specification file when configured, it’ll apply to all these operations.

Property Key Example

quarkus.openapi-generator.[filename].auth.[security_scheme_name].token-propagation=[true,false]

quarkus.openapi-generator.petstore_json.auth.petstore_auth.token-propagation=true
Enables the token propagation for all the operations that are secured with the petstore_auth scheme in the petstore_json file.

quarkus.openapi-generator.[filename].auth.[security_scheme_name].header-name=[http_header_name]

quarkus.openapi-generator.petstore_json.auth.petstore_auth.header-name=MyHeaderName
Says that the authorization token to propagate will be read from the HTTP header MyHeaderName instead of the standard HTTP Authorization header.

Circuit Breaker

You can define the CircuitBreaker annotation from MicroProfile Fault Tolerance in your generated classes by setting the desired configuration in application.properties.

Let’s say you have the following OpenAPI definition:

{
  "openapi": "3.0.3",
  "info": {
    "title": "Simple API",
    "version": "1.0.0-SNAPSHOT"
  },
  "paths": {
    "/hello": {
      "get": {
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/bye": {
      "get": {
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
  }
}

And you want to configure Circuit Breaker for the /bye endpoint, you can do it in the following way:

Add the SmallRye Fault Tolerance extension to your project’s pom.xml file:

<dependency>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-smallrye-fault-tolerance</artifactId>
</dependency>

Assuming your Open API spec file is in src/main/openapi/simple-openapi.json, add the following configuration to your application.properties file:

# Note that the file name must have only alphabetic characters or underscores (_).
quarkus.openapi-generator.codegen.spec.simple_openapi_json.base-package=org.acme.openapi.simple
# Enables the CircuitBreaker extension for the byeGet method from the DefaultApi class
org.acme.openapi.simple.api.DefaultApi/byeGet/CircuitBreaker/enabled=true

With the above configuration, your Rest Clients will be created with a code similar to the following:

package org.acme.openapi.simple.api;

import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;

import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;

import jakarta.ws.rs.*;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.MediaType;

@Path("")
@RegisterRestClient(configKey="simple-openapi_json")
public interface DefaultApi {

    @GET
    @Path("/bye")
    @Produces({ "text/plain" })
    @org.eclipse.microprofile.faulttolerance.CircuitBreaker
    public String byeGet();

    @GET
    @Path("/hello")
    @Produces({ "text/plain" })
    public String helloGet();

}

You can also override the default Circuit Breaker configuration by setting the properties in application.properties just as you would for a traditional MicroProfile application:

org.acme.openapi.simple.api.DefaultApi/byeGet/CircuitBreaker/failOn=java.lang.IllegalArgumentException,java.lang.NullPointerException
org.acme.openapi.simple.api.DefaultApi/byeGet/CircuitBreaker/skipOn=java.lang.NumberFormatException
org.acme.openapi.simple.api.DefaultApi/byeGet/CircuitBreaker/delay=33
org.acme.openapi.simple.api.DefaultApi/byeGet/CircuitBreaker/delayUnit=MILLIS
org.acme.openapi.simple.api.DefaultApi/byeGet/CircuitBreaker/requestVolumeThreshold=42
org.acme.openapi.simple.api.DefaultApi/byeGet/CircuitBreaker/failureRatio=3.14
org.acme.openapi.simple.api.DefaultApi/byeGet/CircuitBreaker/successThreshold=22

See the module circuit-breaker for an example of how to use this feature.

Sending multipart/form-data

The rest client also supports request with mime-type multipart/form-data and, if the schema of the request body is known in advance, we can also automatically generate the models of the request bodies.

RESTEasy Reactive supports multipart/form-data out of the box. Thus, no additional dependency is required.

If you’re using RESTEasy Classic, you need to add the following additional dependency to your pom.xml:

<dependency>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-resteasy-multipart</artifactId>
</dependency>

For any multipart/form-data operation a model for the request body will be generated. Each part of the multipart is a field in this model that is annotated with the following annotations:

  • jakarta.ws.rs.FormParam, where the value parameter denotes the part name,

  • PartType, where the parameter is the jax-rs MediaType of the part (see below for details),

  • and, if the part contains a file, PartFilename, with a generated default parameter that will be passed as the fileName sub-header in the Content-Disposition header of the part.

For example, the model for a request that requires a file, a string and some complex object will look like this:

public class MultipartBody {

    @FormParam("file")
    @PartType(MediaType.APPLICATION_OCTET_STREAM)
    @PartFilename("fileFile")
    public File file;

    @FormParam("fileName")
    @PartType(MediaType.TEXT_PLAIN)
    public String fileName;

    @FormParam("someObject")
    @PartType(MediaType.APPLICATION_JSON)
    public MyComplexObject someObject;
}

Then in the client, when using RESTEasy Classic, the org.jboss.resteasy.annotations.providers.multipart.MultipartForm annotation is added in front of the multipart parameter:

@Path("/echo")
@RegisterRestClient(baseUri="http://my.endpoint.com/api/v1", configKey="multipart-requests_yml")
public interface MultipartService {

    @POST
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    @Produces(MediaType.TEXT_PLAIN)
    String sendMultipartData(@MultipartForm MultipartBody data);

}

When using RESTEasy Reactive, the jakarta.ws.rs.BeanParam annotation is added in front of the multipart parameter:

@Path("/echo")
@RegisterRestClient(baseUri="http://my.endpoint.com/api/v1", configKey="multipart-requests_yml")
public interface MultipartService {

  @POST
  @Consumes(MediaType.MULTIPART_FORM_DATA)
  @Produces(MediaType.TEXT_PLAIN)
  String sendMultipartData(@jakarta.ws.rs.BeanParam MultipartBody data);

}
MultipartForm is deprecated when using RESTEasy Reactive.

baseURI value of RegisterRestClient annotation is extracted from the servers section of the file, if present. If not, it will be left empty and it is expected you set up the uri to be used in your configuration.

Importantly, if some multipart request bodies contain complex objects (i.e. non-primitives) you need to explicitly tell the Open API generator to create models for these objects by setting the skip-form-model property corresponding to your spec in the application.properties to false, e.g.:

quarkus.openapi-generator.codegen.spec.my_multipart_requests_yml.skip-form-model=false

See the module multipart-request for an example of how to use this feature.

In case the default PartFilename annotation is not required, its generation can be disabled by setting the generate-part-filename property (globally or corresponding to your spec) in the application.properties to false, e.g.:

quarkus.openapi-generator.codegen.spec.my_multipart_requests_yml.generate-part-filename=false

By default, the PartFilename value representing the filename is prefixed by the field name. This can be changed by setting the use-field-name-in-part-filename property (globally or corresponding to your spec) in the application.properties to false, e.g.:

quarkus.openapi-generator.codegen.spec.my_multipart_requests_yml.use-field-name-in-part-filename=false

And in case the default PartFilename value is not suitable (e.g. a conversion service only allows/supports specific extensions), the value can be set by using the part-filename-value property (globally or corresponding to your spec) in the application.properties, e.g.:

quarkus.openapi-generator.codegen.spec.my_first_multipart_requests_yml.part-filename-value=".pdf"

So for instance, by setting part-filename-value to some.pdf and use-field-name-in-part-filename to false the generated code will look like this:

public class MultipartBody {

  @FormParam("file")
  @PartType(MediaType.APPLICATION_OCTET_STREAM)
  @PartFilename("some.pdf")
  public File file;
}

And by setting only part-filename-value to .pdf, the generated code will look like this:

public class MultipartBody {

  @FormParam("file")
  @PartType(MediaType.APPLICATION_OCTET_STREAM)
  @PartFilename("file.pdf")
  public File file;
}

See the module part-filename for examples of how to use these features.

Default content-types according to OpenAPI Specification and limitations

The OAS 3.0 specifies the following default content-types for a multipart:

  • If the property is a primitive, or an array of primitive values, the default Content-Type is text/plain

  • If the property is complex, or an array of complex values, the default Content-Type is application/json

  • If the property is a type: string with format: binary or format: base64 (aka a file object), the default Content-Type is application/octet-stream

A different content-type may be defined in your api spec, but this is not yet supported in the code generation. Also, this "annotation-oriented" approach of RestEasy (i.e. using @MultipartForm to denote the multipart body parameter) does not seem to properly support the unmarshalling of arrays of the same type (e.g. array of files), in these cases it uses Content-Type equal to application/json.

Supporting unexpected Enum values

If you are generating a client to an unreliable service, Enums could evolve on the service within a same version without new endpoints. In this case, the client could receive enum values that are unexpected.

To circumvent this, you can generate an UNEXPECTED value with option additional-enum-type-unexpected-member. You can customise the name of this enum with additional-enum-type-unexpected-member-name.

The value can be customised with additional-enum-type-unexpected-member-string-value.

quarkus.openapi-generator.codegen.spec.my_openapi_yaml.additional-enum-type-unexpected-member=true
quarkus.openapi-generator.codegen.spec.my_openapi_yaml.additional-enum-type-unexpected-member.name=UNEXPECTED
quarkus.openapi-generator.codegen.spec.my_openapi_yaml.additional-enum-type-unexpected-member-string-value=unexpected

Generating files via InputStream

Having the files in the src/main/openapi directory will generate the REST stubs by default. Alternatively, you can implement the io.quarkiverse.openapi.generator.deployment.codegen.OpenApiSpecInputProvider interface to provide a list of `InputStream`s of OpenAPI specification files. This is useful in scenarios where you want to dynamically generate the client code without having the target spec file saved locally in your project.

See the example implementation here

Skip Deprecated Attributes in Model classes

The domain objects are classes generated in the model package. These classes might have deprecated attributes in the Open API specification file. By default, these attributes are generated. You can fine tune this behavior if the deprecated attributes should not be generated.

Use the property key <base_package>.model.MyClass.generateDeprecated=false to disable the deprecated attributes in the given model. For example org.acme.weather.Country.generatedDeprecated=false.

Skip Deprecated Operations in API classes

The client objects are classes generated in the api package. These classes might have deprecated operations in the Open API specification file. By default, these operations are generated. You can fine tune this behavior if the deprecated operations should not be generated.

Use the property key <base_package>.api.MyClass.generateDeprecated=false to disable the deprecated operations in the given API. For example org.acme.openapi.simple.api.DefaultApi.generatedDeprecated=false.

package org.acme.openapi.simple.api;

import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;

import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;

import jakarta.ws.rs.*;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.MediaType;

@Path("")
@RegisterRestClient(configKey="simple-openapi_json")
@RegisterProvider(org.test.Foo.class)
@RegisterProvider(org.test.Bar.class)
public interface DefaultApi {

    @GET
    @Path("/bye")
    @Produces({ "text/plain" })
    @org.eclipse.microprofile.faulttolerance.CircuitBreaker
    public String byeGet();
}

See the module integration-tests/register-provider for an example of how to use this feature.

Skip OpenAPI schema validation

Use the property key quarkus.openapi-generator.codegen.validateSpec=false to disable validating the input specification file before code generation. By default, invalid specifications will result in an error.

Type, schema and import mappings

It’s possible to remap types in the generated files. For example, instead of a File you can configure the code generator to use InputStream for all file upload parts of multipart request, or you could change all UUID types to String. You can configure this in your application.properties using the following configuration keys:

Description Property Key Example

Type Mapping

quarkus.openapi-generator.codegen.spec.[filename].type-mappings.[oas_type]

quarkus.openapi-generator.codegen.spec.my_spec_yml.type-mappings.File=InputStream will use InputStream as type for all objects of the OAS File type.

Import Mapping

quarkus.openapi-generator.codegen.spec.[filename].import-mappings.[type]

quarkus.openapi-generator.codegen.spec.my_spec_yml.import-mappings.File=java.io.InputStream will replace the default import java.io.File with import java.io.InputStream

Schema Mapping

quarkus.openapi-generator.codegen.spec.[filename].schema-mappings.[type]

quarkus.openapi-generator.codegen.spec.my_spec_yml.schema-mappings.YearMonth=java.time.YearMonth will use java.time.YearMonth as type for all schemas of the chosen type in the file.

Note that these configuration properties are maps. For the type-mapping the keys are OAS data types and the values are Java types.

Another common example is needing java.time.Instant as type for date-time fields in your POJO classes. You can achieve with these settings:

quarkus.openapi-generator.codegen.spec.my_spec_yml.type-mappings.DateTime=Instant
quarkus.openapi-generator.codegen.spec.my_spec_yml.import-mappings.Instant=java.time.Instant

It’s also possible to only use a type mapping with a fully qualified name, for instance quarkus.openapi-generator.codegen.spec.my_spec_yml.type-mappings.File=java.io.InputStream. For more information and a list of all types see the OpenAPI generator documentation on Type Mappings and Import Mappings and Schema mapping.

See the module type-mapping for an example of how to use this feature.

Config key

By default, the @RegisterRestClient configKey property is the sanitized name of the file containing the OpenAPI spec. For example, if the file name is petstore.json, the configKey will be petstore_json:

/* omitted */
@RegisterRestClient(configKey="petstore_json")
public interface DefaultApi { /* omitted */ }

If you want to use a different configKey than the default one, you can set the quarkus.openapi-generator.codegen.spec.petstore_json.[config-key] property.

Using the config-key the extension allow you to define all allowed properties with quarkus.openapi-generator.codegen.spec.[my_custom_config_key].* prefix. For example:

quarkus.openapi-generator.codegen.spec.petstore_json.config-key=petstore
quarkus.openapi-generator.codegen.spec.petstore.additional-api-type-annotations=@org.test.Foo

With it, you will have the following result:

/* omitted */
@RegisterRestClient(configKey="petstore")
@org.test.Foo
public interface DefaultApi { /* omitted */ }
If you configure the property config-key, it will override the sanitized file name (will not consider the order of the configurations). For example, having the following configuration:
quarkus.openapi-generator.codegen.spec.petstore_json.config-key=custom_config_key
quarkus.openapi-generator.codegen.spec.custom_config_key.additional-api-type-annotations=@org.test.Foo
quarkus.openapi-generator.codegen.spec.petstore_json.additional-api-type-annotations=@org.test.Bar

The generated code will be:

/* omitted */
@RegisterRestClient(configKey="custom_config_key")
@org.test.Foo
public interface DefaultApi { /* omitted */ }

Template Customization

You have the option to swap out the templates used by this extension with your customized versions. To achieve this, place your custom templates under the resources/templates directory. It’s crucial that the filename of each custom template matches that of the original template.

You can find an example of using customized templates in integration-tests/custom-templates.

While the option to replace templates exists, it’s essential to exercise caution and consider this as a final resort. Prior to altering templates, exhaust all possibilities of achieving your goals through configuration settings. Modifying templates could have broader implications for the extension’s functionality and may introduce complexities. Only resort to template replacement when configuration adjustments prove insufficient for your requirements.

Furthermore, be aware that customizing templates increases the risk of compatibility issues during future upgrades. Therefore, exercise discretion and weigh the benefits against the potential risks before opting for template customization.

Additional Properties as Attribute

In some cases is necessary to use additionalProperties inside the OpenAPI specification, by default this extension creates an object that inherits a java.util.HashMap class. It works well, but there are some issues with Jackson on serialize/deserialize:

  • Serialization throws com.fasterxml.jackson.databind.exc.MismatchedInputException exception.

  • Deserialization Jackson does ignore plain fields.

If you want to use composition instead inheritance and serialize/deserialize with Jackson without those problems, consider to configure the additional-properties-as-attributes.

To map additionalProperties as attribute, add the following entry to your properties file. In this example, our spec file is in src/main/openapi/petstore.json:

quarkus.openapi-generator.codegen.spec.petstore_json.additional-properties-as-attribute=true

This configuration implies that all models using additionalProperties will be mapped using a java.util.Map as composition.

Add Additional Request Arguments to each API Method

To add custom request specific parameters you can use the additional-request-args property.

Should work with:

  • @PathParam

  • @QueryParam

  • @CookieParam

  • @FormParam

  • @MatrixParam

To use additional-request-args as attribute, add the following entry to your properties file. In this example, our spec file is in src/main/openapi/petstore.json:

quarkus.openapi-generator.codegen.spec.petstore_json.additional-request-args=@CookieParam("cookie") String cookie;@HeaderParam("x-correlation-id") String correlationId

This configuration is applied to every generated method.

Add Bean Validation support to every API method and validation annotations to all models

To enable bean validation support for validation properties specified in OpenApi.

  • @Valid

  • @Size

  • @Min

  • @Pattern

  • etc.

Example

Given you want to validate parameters of components from my-openapi.yaml file, you must add the following to your application.properties file:

quarkus.openapi-generator.codegen.spec.my_openapi_yaml.use-bean-validation=true

Known Limitations

Supported Arguments

Currently not all arguments are supported by this extension

supported:

unsupported:

(You can extend all endpoints with additional-request-args)

These are the known limitations of this pre-release version:

  • Only Jackson support

We will work in the next few releases to address these use cases, until there please provide feedback for the current state of this extension. We also love contributions .