Quarkus - OpenAPI Generator - Server
Quarkus' extension for generation of server Stubs based on OpenAPI specification files.
This extension is based on the Apicurio Codegen tool.
This extension is for REST code generation for server side only.
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:
<dependency>
<groupId>io.quarkiverse.openapi.generator</groupId>
<artifactId>quarkus-openapi-generator-server</artifactId>
<version>3.0.0-SNAPSHOT</version>
</dependency>
By default, the generated resources are annotated with Microprofile OpenAPI annotations, add the io.quarkus:quarkus-smallrye-openapi
dependency to your project’s pom.xml
file:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-openapi</artifactId>
</dependency>
Note that since this extension has not been yet released, you’ll need a local build of the 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/resources
path and add the OpenAPI spec files there. We support JSON, YAML and YML extensions. You have to define the specification used for code generation with the following property:
quarkus.openapi.generator.spec=petstore-openapi.json
If you want to change the directory where OpenAPI files must be found, use the property quarkus.openapi.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.input-base-dir=openapi-definitions
If a base package name is not provided, it will be used the default io.apicurio.api
. You can customize it with the following property:
quarkus.openapi.generator.base-package=io.petstore
By default, the extension generates non-reactive code. If you would like to change it, you can do it as follows:
quarkus.openapi.generator.reactive=true
Run mvn compile
to generate your classes in target/generated-sources/jaxrs
path:
- io.petstore
- beans
- Address.java
- ApiResponse.java
- Category.java
- Customer.java
- Order.java
- Pet.java
- Tag.java
- User.java
- PetResource.java
- StoreResource.java
- UserResource.java
You can reference the generated code in your project, for example:
package io.petstore;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import io.petstore.beans.ApiResponse;
import io.petstore.beans.Pet;
public class PetStoreImpl implements PetResource {
private static final Map<Long, Pet> PETS = new HashMap<>();
@Override
public Pet updatePet(Pet data) {
return PETS.put(data.getId(), data);
}
@Override
public Pet addPet(Pet data) {
return PETS.put(data.getId(), data);
}
@Override
public List<Pet> findPetsByStatus(String status) {
return null;
}
@Override
public List<Pet> findPetsByTags(List<String> tags) {
return null;
}
@Override
public Pet getPetById(long petId) {
return PETS.get(petId);
}
@Override
public void updatePetWithForm(long petId, String name, String status) {
}
@Override
public void deletePet(String apiKey, long petId) {
PETS.remove(petId);
}
@Override
public ApiResponse uploadFile(long petId, String additionalMetadata, InputStream data) {
return null;
}
}
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.
Codegen Extensions
Apicurio Codegen Extensions use OpenAPI specification extensions to allow customization of the generated source code based on your API contract.
The following extensions modify the behavior of the code generation in specific parts of the OpenAPI document.
x-codegen-package
The x-codegen-package
extension allows you to define the package where a generated class should be placed. This extension is applicable to components of type schema
.
Where to use | components.schemas.<SchemaName>.x-codegen-package |
---|
{
"components": {
"schemas": {
"ArtifactState": {
"description": "Describes the state of an artifact or artifact version. The following states\nare possible:\n\n* ENABLED\n* DISABLED\n* DEPRECATED\n",
"enum": [
"ENABLED",
"DISABLED",
"DEPRECATED"
],
"type": "string",
"x-codegen-package": "io.apicurio.registry.types"
}
}
}
}
This configuration generates the ArtifactState
class in the package io.apicurio.registry.types
:
package io.apicurio.registry.types;
public enum ArtifactState {
ENABLED, DISABLED, DEPRECATED
}
x-codegen-async
The x-codegen-async
extension allows you to define whether a generated method should return asynchronously (e.g., wrapped in CompletionStage
). This extension can be used on any HTTP operation (get
, post
, etc.).
Where to use | paths.<path>.<operation>.x-codegen-async |
---|
"/cart/ids": {
"get": {
"summary": "Get a cart by ID",
"operationId": "getCartByID",
"description": "Get a cart resource by ID",
"tags": [
"Cart"
],
"x-codegen-async": true
}
}
This configuration generates the following asynchronous JAX-RS method:
@Path("/cart/ids")
@GET
@Produces("application/json")
CompletionStage<String> getCartByID();
x-codegen-returnType
The x-codegen-returnType
extension allows you to explicitly define the return type of a generated method, overriding the type inferred from the schema. This is useful for advanced use cases, such as returning reactive types, server-sent events (SSE), or custom wrappers.
Where to use | paths.<path>.<operation>.responses.<statusCode>.content.<mediaType>.x-codegen-returnType |
---|
"responses": {
"200": {
"description": "A continuous stream of cart IDs",
"content": {
"text/event-stream": {
"schema": {
"type": "string"
},
"x-codegen-returnType": "io.smallrye.mutiny.Multi<String>",
}
}
}
}
This configuration generates the following method using the specified return type (Multi<String>
from Mutiny):
import io.smallrye.mutiny.Multi;
/* omitted for simplicity */
@Produces("text/event-stream")
Multi<String> getCartIds();
x-codegen-annotations
The x-codegen-annotations
extension allows you to add annotations to the generated code. This extension is supported in two specific contexts:
Where to use | - components.schemas.<SchemaName>.x-codegen-annotations (adds annotations at the class level)- paths.<path>.<operation>.parameters[].x-codegen-annotations (adds annotations to method parameters) |
---|
"MyQuarkusBean": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"description": {
"type": "string"
}
},
"x-codegen-annotations": [
"io.quarkus.runtime.annotations.RegisterForReflection"
]
}
This results in the following class-level annotation:
@RegisterForReflection
public class MyQuarkusBean {
private String name;
private String description;
}
"parameters": [
{
"name": "beerId",
"in": "path",
"required": true,
"description": "Unique ID of a beer.",
"schema": {
"type": "integer",
"format": "int32"
},
"x-codegen-annotations": [
"@jakarta.validation.constraints.Positive(message = \"The beerId must be a natural number!\")"
]
}
]
This adds the annotation to the generated method parameter:
public Response deleteBeer(
@Positive(message = "The beerId must be a natural number!") int beerId
);
x-codegen-contextRoot
The x-codegen-contextRoot
extension allows you to define a base path (context root) that is prepended to all generated endpoint paths.
Where to use | x-codegen-contextRoot should be placed at the root level of the OpenAPI document (next to info , paths , etc.) |
---|
{
"openapi": "3.0.2",
"info": {
"title": "Context Root Sample API",
"version": "1.0.0"
},
"paths": {
"/widgets": {
"get": {
"operationId": "getWidgets",
"summary": "Get widgets",
"responses": {
"200": {
"description": "Returns the list of widgets.",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
}
}
}
},
"x-codegen-contextRoot": "/api/v3"
}
This configuration prepends /api/v3
to all paths, resulting in:
@Path("/api/v3/widgets")
public interface WidgetsResource {
@Operation(summary = "Get widgets", operationId = "getWidgets")
@GET
@Produces("application/json")
List<String> getWidgets();
}
x-codegen-formatPattern
The x-codegen-formatPattern
extension allows you to customize the date/time format pattern used for serialization and deserialization of date fields.
Where to use | components.schemas.<SchemaName>.properties.<propertyName>.x-codegen-formatPattern |
---|
"VersionMetaData": {
"type": "object",
"properties": {
"createdOn": {
"type": "string",
"format": "date-time",
"x-codegen-formatPattern": "yyyy-MM-dd'T'HH:mm:ss"
}
}
}
This generates the following annotated field:
@JsonFormat(
shape = Shape.STRING,
pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'",
timezone = "UTC"
)
@JsonProperty("createdOn")
private Date createdOn;
x-codegen-inline / x-codegen-inlined
The x-codegen-inline
(or x-codegen-inlined
) extension indicates that a schema should be inlined directly into the property where it is referenced, rather than generating a separate Java class.
This is useful for simplifying the generated model when the referenced schema is small or generic, such as maps or simple value types.
Where to use | components.schemas.<SchemaName>.x-codegen-inline components.schemas.<SchemaName>.x-codegen-inlined |
---|
Both x-codegen-inline
and x-codegen-inlined
are aliases and behave the same way.
"MyMap": {
"type": "object",
"additionalProperties": {
"type": "string"
},
"x-codegen-type": "StringMap",
"x-codegen-inline": true
}
When another schema references MyMap
, it will be inlined as Map<String, String>
instead of generating a separate MyMap
Java class.
@JsonProperty("mymap")
private Map<String, String> mymap;
If the extension was not present, the field would instead be generated with a custom type:
@JsonProperty("mymap")
private MyMap mymap;
x-codegen-type
The x-codegen-type
extension is used to override the type of a generated bean class. It is especially important when combined with x-codegen-inline
.
Why use x-codegen-type
?
When using x-codegen-inline: true
, the code generator will not generate a Java class for the given schema. However, in order to correctly reference the type in generated code, it still needs to know the Java type to use in place of the schema.
Without x-codegen-type
, the code generator won’t know what type to substitute, and this will result in an error during code generation.
x-codegen-extendsClass
This extension allows the generated Java class to extend a custom base class.
Usage
You must define the fully qualified class name in the OpenAPI schema using the x-codegen-extendsClass
property.
Example OpenAPI Specification
{
"openapi": "3.0.2",
"info": {
"title": "Schema Extends API",
"version": "1.0.0"
},
"paths": {},
"components": {
"schemas": {
"MySchema": {
"type": "object",
"x-codegen-type": "bean",
"x-codegen-extendsClass": "io.quarkus.openapi.generator.server.AbstractSchema",
"properties": {
"name": {
"type": "string"
},
"description": {
"type": "string"
}
}
}
}
}
}
Configuration Properties
Configuration property fixed at build time - All other configuration properties are overridable at runtime
Configuration property |
Type |
Default |
---|---|---|
The OpenAPI specification filename. Environment variable: |
string |
|
The input base dir where the OpenAPI specification is. Environment variable: |
string |
|
Whether it must generate with reactive code. Environment variable: |
boolean |
|
Whether it must generate builders for properties. Environment variable: |
boolean |
|
The base package to be used to generated sources. Environment variable: |
string |
|
Whether it must generate resources and beans using bean validation (JSR-303). Environment variable: |
boolean |
|