$ mn create-app my-openapi-app --features swagger-java
Table of Contents
OpenAPI/Swagger Support
Configuration to integrate Micronaut and OpenAPI/Swagger
Version:
1 Introduction
Micronaut includes support for producing OpenAPI (Swagger) YAML at compilation time. Micronaut will at compile time produce a Swagger 3.x compliant YAML file just based on the regular Micronaut annotations and the javadoc comments within your code.
You can customize the generated Swagger using the standard Swagger Annotations.
2 Using the Micronaut CLI
To create a project with OpenAPI/Swagger support using the Micronaut CLI, supply the swagger-*
feature to the features
flag. For example:
This will create a project with the minimum necessary configuration for OpenAPI.
If you have already created a Micronaut project and will like to add Swagger support, you can simply follow instructions in subsequent sections.
3 Getting Started with Swagger
To enable this support you should add the following dependencies to your build configuration:
annotationProcessor("io.micronaut.configuration:micronaut-openapi:1.5.1")
<annotationProcessorPaths>
<path>
<groupId>io.micronaut.configuration</groupId>
<artifactId>micronaut-openapi</artifactId>
<version>1.5.1</version>
</path>
</annotationProcessorPaths>
Then the following compile time dependency:
implementation("io.swagger.core.v3:swagger-annotations")
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-annotations</artifactId>
</dependency>
1 | The openapi configuration gets added into the annotation processor scope |
2 | The Swagger Annotations are added to the compile classpath |
For Kotlin the openapi dependency should be in the kapt scope and for Groovy in the compileOnly scope.
|
Once dependencies have been configured a minimum requirement is to add a @OpenAPIDefinition
annotation to your Application
class:
import io.micronaut.runtime.Micronaut;
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.info.Contact;
import io.swagger.v3.oas.annotations.info.Info;
import io.swagger.v3.oas.annotations.info.License;
@OpenAPIDefinition(
info = @Info(
title = "Hello World",
version = "0.0",
description = "My API",
license = @License(name = "Apache 2.0", url = "https://foo.bar"),
contact = @Contact(url = "https://gigantic-server.com", name = "Fred", email = "Fred@gigagantic-server.com")
)
)
public class Application {
public static void main(String[] args) {
Micronaut.run(Application.class);
}
}
import io.micronaut.runtime.Micronaut
import groovy.transform.CompileStatic
import io.swagger.v3.oas.annotations.*
import io.swagger.v3.oas.annotations.info.*
@OpenAPIDefinition(
info = @Info(
title = "Hello World",
version = "0.0",
description = "My API",
license = @License(name = "Apache 2.0", url = "https://foo.bar"),
contact = @Contact(url = "https://gigantic-server.com", name = "Fred", email = "Fred@gigagantic-server.com")
)
)
@CompileStatic
class Application {
static void main(String[] args) {
Micronaut.run(Application)
}
}
import io.micronaut.runtime.Micronaut
import io.swagger.v3.oas.annotations.OpenAPIDefinition
import io.swagger.v3.oas.annotations.info.Contact
import io.swagger.v3.oas.annotations.info.Info
import io.swagger.v3.oas.annotations.info.License
@OpenAPIDefinition(
info = Info(
title = "Hello World",
version = "0.0",
description = "My API",
license = License(name = "Apache 2.0", url = "https://foo.bar"),
contact = Contact(url = "https://gigantic-server.com", name = "Fred", email = "Fred@gigagantic-server.com")
)
)
object Application {
@JvmStatic
fun main(args: Array<String>) {
Micronaut.run(Application.javaClass)
}
}
With that in place you compile your project and a Swagger YAML file will be generated to the META-INF/swagger
directory of your project’s class output. For example the above configuration for Java will be generated to build/classes/java/main/META-INF/swagger/hello-world-0.0.yml
and build/tmp/kapt3/classes/main/META-INF/swagger/hello-world-0.0.yml
for Kotlin.
The previously defined annotations will produce YAML like the following:
openapi: 3.0.1
info:
title: the title
description: My API
contact:
name: Fred
url: https://gigantic-server.com
email: Fred@gigagantic-server.com
license:
name: Apache 2.0
url: https://foo.bar
version: "0.0"
4 Open API Processing Options
In the following chapters you will see it is possible to tweaks the open api processing via system properties. It is also possible to specify these options in
a file located at the root level of your project directory. The expected filename is openapi.properties
.
It is possible to specify a different location and filename with the micronaut.openapi.config.file
System property.
Options specified with System properties have priority over the one defined in the openapi.properties
file.
micronaut.openapi.property.naming.strategy=KEBAB_CASE
micronaut.openapi.target.file=myspecfile.yml
swagger-ui.enabled=true
redoc.enabled=true
rapidoc.enabled=true
rapidoc.bg-color=#14191f
rapidoc.text-color=#aec2e0
rapidoc.sort-endpoints-by=method
Properties prefixed with micronaut.openapi.expand
will be expanded at compile time, for instance with:
micronaut.openapi.expand.api.version=v1.1
micronaut.openapi.expand.openapi.description=A nice API
And:
@OpenAPIDefinition(
info = @Info(
title = "Hello World",
version = "${api.version}",
description = "${openapi.description}",
license = @License(name = "Apache 2.0", url = "https://foo.bar"),
contact = @Contact(url = "https://gigantic-server.com", name = "Fred", email = "Fred@gigagantic-server.com")
)
)
public class Application {
public static void main(String[] args) {
Micronaut.run(Application.class);
}
}
The generated specification file will looks like:
openapi: 3.0.1
info:
title: the title
description: A nice API
contact:
name: Fred
url: https://gigantic-server.com
email: Fred@gigagantic-server.com
license:
name: Apache 2.0
url: https://foo.bar
version: "v1.1"
5 Exposing Swagger Output
If you wish to expose the generated Swagger output from your running application you can simply add the necessary static resource configuration to src/main/resources/application.yml. For example:
micronaut:
router:
static-resources:
swagger:
paths: classpath:META-INF/swagger
mapping: /swagger/**
With the above configuration in place when you run your application you can access your Swagger documentation at http://localhost:8080/swagger/hello-world-0.0.yml
.
6 Generating OpenAPI Views
Micronaut can generate views for your generated OpenApi specification. Currently Swagger-ui, Redoc and RapiDoc are supported. You can also use RapiPdf to generate a PDF from your spec file.
The resources needed to render the views (javascript, css, …) are loaded from CDNs: unpkg.com and fonts.googleapis.com.
By default the generation of views is disabled. To turn it on you have to set the following system property micronaut.openapi.views.spec
.
The string syntax is a series of comma-separated key-value pairs, to enable and configure the views.
micronaut.openapi.views.spec=redoc.enabled=true,rapidoc.enabled=true,swagger-ui.enabled=true,swagger-ui.theme=flattop
For instance in Gradle for Kotlin projects:
JAVA_TOOL_OPTIONS=-Dmicronaut.openapi.views.spec=redoc.enabled=true,rapidoc.enabled=true,swagger-ui.enabled=true,swagger-ui.theme=flattop \
./gradlew --no-daemon clean assemble
or in build.gradle as well:
kapt {
arguments {
arg("micronaut.openapi.views.spec", "redoc.enabled=true,rapidoc.enabled=true,swagger-ui.enabled=true,swagger-ui.theme=flattop")
}
}
or in Gradle for Java projects:
tasks.withType(JavaCompile) {
options.fork = true
options.forkOptions.jvmArgs << '-Dmicronaut.openapi.views.spec=rapidoc.enabled=true,swagger-ui.enabled=true,swagger-ui.theme=flattop'
...
}
or in Maven:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<fork>true</fork>
<compilerArgs>
<arg>-J-Dmicronaut.openapi.views.spec=rapidoc.enabled=true,swagger-ui.enabled=true,swagger-ui.theme=flattop</arg>
...
</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>
or in Maven with Groovy:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.0.0</version>
<executions>
<execution>
<goals>
<goal>set-system-properties</goal>
</goals>
<configuration>
<properties>
<property>
<name>micronaut.openapi.views.spec</name>
<value>rapidoc.enabled=true,swagger-ui.enabled=true,swagger-ui.theme=flattop</value>
</property>
</properties>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
The views will be generated to the META-INF/swagger/views/[swagger-ui | redoc | rapidoc]
directory of your project’s class output.
The following properties are supported:
-
mapping.path=[string]
: The path from where the swagger specification will be served by the http server. Default isswagger
. -
redoc.enabled=[true | false]
: When 'true' the Redoc view is generated. -
rapidoc.enabled=[true | false]
: When 'true' the RapiDoc view is generated. -
swagger-ui.enabled=[true | false]
: When 'true' the Swagger-ui view is generated. -
redoc.version=[string]
: The version of Redoc to use. Default is to use the latest available. -
redoc.[expand-single-schema-field, expand-default-server-variables, menu-toggle, only-required-in-samples, payload-sample-idx, sort-props-alphabetically, untrusted-spec, expand-responses, show-extensions, native-scrollbars, path-in-middle-panel, suppress-warnings, hide-hostname, disable-search, json-sample-expand-level, scroll-y-offset, hide-download-button, no-auto-auth, theme, hide-single-request-sample-tab, required-props-first, hide-loading]
. See Redoc Options for a description. -
rapidoc.version=[string]
: The version of RapiDoc to use. Default is to use the latest available. -
rapidoc.[style, sort-tags, sort-endpoints-by, heading-text, goto-path, theme, bg-color, text-color, header-color, primary-color, regular-font, mono-font, nav-bg-color, nav-text-color, nav-hover-bg-color, nav-hover-text-color, nav-accent-color, nav-item-spacing, layout, render-style, schema-style, schema-expand-level, schema-description-expanded, default-schema-tab, response-area-height, show-info, info-description-headings-in-navbar, show-components, show-header, allow-authentication, allow-spec-url-load, allow-spec-file-load, allow-search, allow-try, allow-server-selection, api-key-name, api-key-value, api-key-location, server-url, default-api-server]
. See RapiDoc Options for a description. -
swagger-ui.version=[string]
: The version of Swagger-ui to use. Default is to use the latest available. -
swagger-ui.[displayOperationId, oauth2RedirectUrl, showMutatedRequest, deepLinking, supportedSubmitMethods, defaultModelsExpandDepth, layout, defaultModelRendering, docExpansion, filter, validatorUrl, showCommonExtensions, maxDisplayedTags, withCredentials, displayRequestDuration, showExtensions]
. See Swagger UI Configuration for a description. -
swagger-ui.theme=[DEFAULT | MATERIAL | FEELING_BLUE | FLATTOP | MONOKAI | MUTED | NEWSPAPER | OUTLINE]
: The theme of swagger-ui to use. These are case insensitive. Default isDEFAULT
. See Swagger UI Themes.
Views also supports RapiPdf, to enable it use rapipdf.enabled=true
.
It will add a button to the view to generate a PDF from the spec file.
RapiPdf supports the following options:
-
rapipdf.[include-api-details, pdf-title, include-api-list, include-security, input-bg, hide-input, pdf-footer-text, button-bg, pdf-primary-color, pdf-schema-style, button-label, pdf-alternate-color, include-info, include-toc, button-color, style, input-color]
. See RapiPdf Attributes for a description.
To expose the views, you also must expose the generated yaml
:
micronaut:
router:
static-resources:
swagger:
paths: classpath:META-INF/swagger
mapping: /swagger/**
redoc:
paths: classpath:META-INF/swagger/views/redoc
mapping: /redoc/**
rapidoc:
paths: classpath:META-INF/swagger/views/rapidoc
mapping: /rapidoc/**
swagger-ui:
paths: classpath:META-INF/swagger/views/swagger-ui
mapping: /swagger-ui/**
With the above configuration in place when you run your application you can access your Swagger documentation at http://localhost:8080/[redoc|rapidoc|swagger-ui].
By default the views expect to find the yaml
under /swagger
, if you change this mapping to something else:
micronaut:
router:
static-resources:
swagger:
paths: classpath:META-INF/swagger
mapping: /swaggerYAML/**
....
You will need to set the mapping.path
property accordingly: micronaut.openapi.views.spec=mapping.path=swaggerYAML…
.
Server Context Path
In micronaut configuration file you can define a server context path (with micronaut.server.context-path
) which serves as a base path for all routes.
Since the yaml specification file and the views are generated at compile time, these resources are not aware of this runtime setting.
It is still possible for the views to work in case a context path is defined:
* Set micronaut.openapi.server.context.path
property for compile time resolution,
* Use a HttpServerFilter
that will add a cookie, or
* Add a parameter to the url.
The view will first look for the cookie and if not present for the parameter.
Compile Time Resolution
Either set micronaut.openapi.server.context.path
as a System Property or in openapi.properties
, then all paths will be prepend with the
specified value at compile time.
If you want the resolution of the context path at runtime use one of the following methods:
HttpServerFilter
Create a HttpServerFilter
that will add a cookie with name contextPath
.
import java.time.Duration;
import org.reactivestreams.Publisher;
import io.micronaut.context.annotation.Requires;
import io.micronaut.context.annotation.Value;
import io.micronaut.core.async.publisher.Publishers;
import io.micronaut.http.HttpMethod;
import io.micronaut.http.HttpRequest;
import io.micronaut.http.MutableHttpResponse;
import io.micronaut.http.annotation.Filter;
import io.micronaut.http.cookie.Cookie;
import io.micronaut.http.filter.HttpServerFilter;
import io.micronaut.http.filter.ServerFilterChain;
@Requires(property = "micronaut.server.context-path")
@Filter(methods = {HttpMethod.GET, HttpMethod.HEAD}, patterns = {"/**/rapidoc*", "/**/redoc*", "/**/swagger-ui*"})
public class OpenApiViewCookieContextPathFilter implements HttpServerFilter {
private final Cookie contextPathCookie;
OpenApiViewCookieContextPathFilter(@Value("${micronaut.server.context-path}") String contextPath) {
this.contextPathCookie = Cookie.of("contextPath", contextPath).maxAge(Duration.ofMinutes(2L));
}
@Override
public Publisher<MutableHttpResponse<?>> doFilter(HttpRequest<?> request, ServerFilterChain chain) {
return Publishers.map(chain.proceed(request), response -> response.cookie(contextPathCookie));
}
}
URL Parameter
Just add a parameter to the view url. For instance if the context path is set to /context/path
you will access your view with http://localhost:8080/context/path/swagger-ui?contextPath=%2Fcontext%2Fpath
.
7 Exposing Endpoints
It is possible to expose management Endpoints in the openapi specification file.
You need to exposed micronaut-management
as annotation processor and runtime dependency:
annotationProcessor("io.micronaut:micronaut-management:1.5.1")
<annotationProcessorPaths>
<path>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-management</artifactId>
<version>1.5.1</version>
</path>
</annotationProcessorPaths>
implementation("io.micronaut:micronaut-management:1.5.1")
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-management</artifactId>
<version>1.5.1</version>
</dependency>
User Defined Endpoints
To process user defined endpoints simply add:
endpoints.enabled=true
in the openapi.properties
file.
Tags
You can also provide some tags for all endpoints with the endpoints.tags=<comma separated list of tags>
flag, for instance:
endpoints.tags=Management Enpoints
Servers
You can also provide some servers for all endpoints with the endpoints.server=<json array of io.swagger.v3.oas.models.servers.Server>
flag, for instance:
endpoints.servers=[ \ { \ "url": "https://{username}.gigantic-server.com:{port}/{basePath}", \ "description": "The production API server", \ "variables": { \ "username": { \ "default": "demo", \ "description": "this value is assigned by the service provider, in this example `gigantic-server.com`" \ }, \ "port": { \ "enum": [ \ "8443", \ "443" \ ], \ "default": "8443" \ }, \ "basePath": { \ "default": "v2" \ } \ } \ } \ ]
Security Requirements
You can also provide some security requirements for all endpoints with the endpoints.security-requirements=<json array of io.swagger.v3.oas.models.security.SecurityRequirement>
flag, for instance:
endpoints.security-requirements=[{"api_key": []}]
Don’t forget to declare the referenced SecurityScheme
.
Path
If you are using a custom path for your endpoints use endpoints.path
to set it:
endpoints.path=/endpoints
Micronaut Built-In Endpoints
To enable the processing of built-in endpoints (https://docs.micronaut.io/latest/guide/index.html#providedEndpoints), you have to declare them in the
openapi.properties
file:
endpoints.enabled=true endpoints.tags=Management Endpoints endpoints.routes.class=io.micronaut.management.endpoint.routes.RoutesEndpoint endpoints.beans.class=io.micronaut.management.endpoint.beans.BeansEndpoint endpoints.health.class=io.micronaut.management.endpoint.health.HealthEndpoint endpoints.loggers.class=io.micronaut.management.endpoint.loggers.LoggersEndpoint endpoints.refresh.class=io.micronaut.management.endpoint.refresh.RefreshEndpoint
The syntax is the following: endpoints.<name>.class=<full class name of the endpoint>
where name
is an arbitrary name.
You can also add some tags, servers and security requirements to each endpoint:
endpoints.refresh.class=io.micronaut.management.endpoint.refresh.RefreshEndpoint endpoints.refresh.servers=[{"url": "https://staging.gigantic-server.com/v1", "description": "Staging server"}] endpoints.refresh.security-requirements=[{"petstore_auth": ["write:pets", "read:pets"]}]
8 Controllers and Swagger Annotations
By default Micronaut will automatically at compile time build out the Swagger YAML definition from your defined controllers and methods. For example given the following class:
import io.micronaut.http.MediaType;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.micronaut.validation.Validated;
import io.reactivex.Single;
@Validated
@Controller("/")
public class HelloController {
/**
* @param name The person's name
* @return The greeting
*/
@Get(uri = "/hello/{name}", produces = MediaType.TEXT_PLAIN)
public Single<String> index(String name) {
return Single.just("Hello " + name + "!");
}
}
import io.micronaut.http.MediaType
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Get
import io.micronaut.validation.Validated
import io.reactivex.Single
@Validated
@Controller("/")
class HelloController {
/**
* @param name The person's name
* @return The greeting
*/
@Get(uri = "/hello/{name}", produces = MediaType.TEXT_PLAIN)
Single<String> index(String name) {
return Single.just("Hello $name!")
}
}
import io.micronaut.http.MediaType
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Get
import io.micronaut.validation.Validated
import io.reactivex.Single
@Validated
@Controller("/")
open class HelloController {
/**
* @param name The person's name
* @return The greeting
*/
@Get(uri = "/hello/{name}", produces = [MediaType.TEXT_PLAIN])
open fun index(name: String): Single<String> {
return Single.just("Hello $name!")
}
}
The resulting output will be:
openapi: 3.0.1
info:
title: Hello World
description: My API
contact:
name: Fred
url: https://gigantic-server.com
email: Fred@gigagantic-server.com
license:
name: Apache 2.0
url: https://foo.bar
version: "0.0"
paths:
/hello/{name}:
get:
description: ""
operationId: index
parameters:
- name: name
in: path
description: The person's name
required: true
schema:
type: string
responses:
default:
description: The greeting
content:
text/plain:
schema:
type: string
Notice how the javadoc comments are used to fill out the description of the API. If this is not desirable then you can take full control by augmenting your definition with Swagger annotations:
import io.micronaut.http.MediaType;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.micronaut.validation.Validated;
import io.reactivex.Single;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import javax.validation.constraints.NotBlank;
@Controller("/")
@Validated
public class HelloController {
/**
* @param name The person's name
* @return The greeting message
*/
@Get(uri="/greetings/{name}", produces= MediaType.TEXT_PLAIN)
@Operation(summary = "Greets a person",
description = "A friendly greeting is returned"
)
@ApiResponse(
content = @Content(mediaType = "text/plain",
schema = @Schema(type="string"))
)
@ApiResponse(responseCode = "400", description = "Invalid Name Supplied")
@ApiResponse(responseCode = "404", description = "Person not found")
@Tag(name = "greeting")
public Single<String> greetings(@Parameter(description="The name of the person") @NotBlank String name) {
return Single.just("Hello " + name + ", How are you doing?");
}
}
@Controller("/")
@Validated
class HelloController {
/**
* @param name The person's name
* @return The greeting message
*/
@Get(uri="/greetings/{name}", produces= MediaType.TEXT_PLAIN)
@Operation(summary = "Greets a person",
description = "A friendly greeting is returned"
)
@ApiResponse(
content = @Content(mediaType = "text/plain",
schema = @Schema(type="string"))
)
@ApiResponse(responseCode = "400", description = "Invalid Name Supplied")
@ApiResponse(responseCode = "404", description = "Person not found")
@Tag(name = "greeting")
Single<String> greetings(@Parameter(description="The name of the person") @NotBlank String name) {
return Single.just("Hello $name, How are you doing?")
}
}
import io.micronaut.http.MediaType
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Get
import io.micronaut.validation.Validated
import io.reactivex.Single
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.media.Content
import io.swagger.v3.oas.annotations.media.Schema
import io.swagger.v3.oas.annotations.responses.ApiResponse
import io.swagger.v3.oas.annotations.responses.ApiResponses
import io.swagger.v3.oas.annotations.tags.Tag
@Controller("/")
@Validated
open class HelloController {
/**
* @param name The person's name
* @return The greeting message
*/
@Get(uri = "/greetings/{name}", produces = [MediaType.TEXT_PLAIN])
@Operation(summary = "Greets a person", description = "A friendly greeting is returned")
// Please Note: Repeatable Annotations with non-SOURCE retentions are not yet supported with Kotlin so we are using `@ApiResponses`
// instead of `@ApiResponse`, see https://youtrack.jetbrains.com/issue/KT-12794
@ApiResponses(
ApiResponse(content = [Content(mediaType = "text/plain", schema = Schema(type = "string"))]),
ApiResponse(responseCode = "400", description = "Invalid Name Supplied"),
ApiResponse(responseCode = "404", description = "Person not found")
)
@Tag(name = "greeting")
open fun greetings(name: String): Single<String> {
return Single.just("Hello $name, how are you doing?")
}
}
The resulting output will be:
openapi: 3.0.1
info:
title: Hello World
description: My API
contact:
name: Fred
url: https://gigantic-server.com
email: Fred@gigagantic-server.com
license:
name: Apache 2.0
url: https://foo.bar
version: "0.0"
paths:
/greetings/{name}:
get:
tags:
- greeting
summary: Greets a person
description: A friendly greeting is returned
operationId: greetings
parameters:
- name: name
in: path
description: The name of the person
required: true
schema:
minLength: 1
type: string
responses:
default:
content:
text/plain:
schema:
type: string
400:
description: Invalid Name Supplied
404:
description: Person not found
You can control how the Schema property names are dumped by setting the micronaut.openapi.property.naming.strategy
system property. It accepts one of
the following jackson's PropertyNamingStrategy
:
- SNAKE_CASE,
- UPPER_CAMEL_CASE,
- LOWER_CAMEL_CASE,
- LOWER_CASE and
- KEBAB_CASE.
For instance in gradle:
tasks.withType(JavaCompile) {
options.fork = true
options.forkOptions.jvmArgs << '-Dmicronaut.openapi.property.naming.strategy=SNAKE_CASE'
...
}
or in maven:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<fork>true</fork>
<compilerArgs>
<arg>-J-Dmicronaut.openapi.property.naming.strategy=SNAKE_CASE</arg>
...
</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>
9 Schemas and POJOs
If you return types are not simple strings and primitive types then Micronaut will attempt to generate a Schema definition. You can customize the
generation of the Schema by using the @Schema
annotation on your POJO. For example:
@Schema(name="MyPet", description="Pet description") (1)
class Pet {
private PetType type;
private int age;
private String name;
public void setAge(int a) {
age = a;
}
/**
* The age
*/
@Schema(description="Pet age", maximum="20") (2)
public int getAge() {
return age;
}
public void setName(String n) {
name = n;
}
@Schema(description="Pet name", maxLength=20)
public String getName() {
return name;
}
public void setType(PetType t) {
type = t;
}
public PetType getType() {
return type;
}
}
enum PetType {
DOG, CAT;
}
1 | The @Schema annotation is used to customize the name of the schema |
2 | Properties can be customized too. |
10 Schemas and Meta Annotations
If you don’t have control of the source code and don’t want to have to annotate each parameter with @Schema
then it can be convenient to instead use a meta annotation.
For example if the aforementioned Pet
class cannot be annotated with @Schema
you can define a meta annotation:
@Documented
@Retention(RUNTIME)
@Target({ElementType.PARAMETER, ElementType.FIELD})
@Schema(name="MyPet", description="Pet description")
@interface MyAnn {
}
Then whenever Pet
is used as a parameter you can annotate the parameter with @MyAnn
.
11 Schemas and Generics
If a method return type includes generics then these will included when calculating the schema name. For example the following:
class Response<T> {
private T r;
public T getResult() {
return r;
};
}
@Controller("/")
class MyController {
@Put("/")
public Response<Pet> updatePet(Pet pet) {
...
}
}
Will result in a schema called #/components/schemas/Response<Pet>
being generated. If you wish to alter the name of the schema you can do so with the @Schema
annotation:
@Put("/")
@Schema(name="ResponseOfPet")
public Response<Pet> updatePet(Pet pet) {
...
}
In the above case the generated schema will be named #/components/schemas/ResponseOfPet
.
12 Merging Schemas
Often times you might want to generate OpenAPI (Swagger) YAML for built-in endpoints or paths from some other modules, such as security
. In order to generate YAML including all that information, Micronaut supports merging of multiple OpenAPI YAML files. So, you can create OpenAPI YAML files manually at some predefined path from where the information will then be merged into the final YAML file.
To configure the path for additional swagger files you need to set System
property micronaut.openapi.additional.files
. For example:
micronaut.openapi.additional.files={project.home}/src/test/resources/swagger
13 Repository
You can find the source code of this project in this repository: