I want to switch to the Micronaut framework from Spring Boot 2. And I am struggling with the Swagger settings.
In Spring Boot 2 project I have the following dependencies:
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.6.1</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.6.1</version>
</dependency>
and SwaggerConfig.class:
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket swagger() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(getApiInfo())
.select()
.apis(RequestHandlerSelectors.withClassAnnotation(RestController.class))
.paths(PathSelectors.any())
.build();
}
private ApiInfo getApiInfo() {
return new ApiInfo("test",
"",
"",
"",
new Contact("", "https://test.test", ""),
"",
"");
}
}
And it works perfectly starting up swagger-ui along with the Spring Boot 2 application.
Which dependencies should I add to maven and which classes should I create to obtain the same result for the Micronaut project?
Assuming the application is already created, add the following to you pom.xml
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-annotations</artifactId>
<version>${swagger.version}</version>
<scope>compile</scope>
</dependency>
where the property swagger.version is set to 2.0.3
add the following to you annotationProcessorPaths in the maven-compiler-plugin
<path>
<groupId>io.micronaut.configuration</groupId>
<artifactId>micronaut-openapi</artifactId>
<version>${micronaut.version}</version>
</path>
Then add the following to your micronaut router section.
micronaut:
router:
static-resources:
swagger:
paths: classpath:META-INF/swagger
mapping: ${application.api.swagger.path}/**
This will expose your swagger/oas yml file that is generated during compile, provided you use the configuration below. You can of course change the ${application.api.swagger.path}
to just be /api-docs/swagger
or something to your liking.
As described in the docs, you can also do the following --features=swagger-java
to add the above dependecies when you initially create the project.
If you want to render the api-specification from the application itself, then you need to add some more code. The following example is probably more fleshed out than it needs to be, but for my purpose the application serves as a central renderer for swagger/oas specifications.
First add a controller for you swagger needs, and annotate the controller with @Hidden
to make sure it doesn't get processed by the annotation processor.
@Hidden
@Controller("/api")
public class SwaggerController {
@Inject
SwaggerConfig config;
@View("swagger/index")
@Get
public SwaggerConfig index() {
return config;
}
}
Then add the following configuration class, which binds the properties from below
@ConfigurationProperties(SwaggerConfig.PREFIX)
public class SwaggerConfig {
public static final String PREFIX = "application.api.swagger";
private String version;
private String layout;
private boolean deepLinking;
private List<URIConfig> urls;
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getLayout() {
return layout;
}
public void setLayout(String layout) {
this.layout = layout;
}
public boolean isDeepLinking() {
return deepLinking;
}
public void setDeepLinking(boolean deepLinking) {
this.deepLinking = deepLinking;
}
public List<URIConfig> getUrls() {
return urls;
}
public void setUrls(List<URIConfig> urls) {
this.urls = urls;
}
@ConfigurationProperties(URIConfig.PREFIX)
public static class URIConfig {
static final String PREFIX = "urls";
private String name;
private String url;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
}
The above config class binds the following configuration from application.yml, but needs to be placed before the micronaut specific configuration.
application:
api:
swagger:
path: /api-docs/swagger
version: 3.19.4
layout: StandaloneLayout
deepLinking: true
urls:
- name: ubw-rest
url: /api-docs/swagger/ubw-rest-0.1.yml
When that is done, add the following handlebars/mustache dependency to the pom
<dependency>
<groupId>com.github.jknack</groupId>
<artifactId>handlebars</artifactId>
<version>4.1.0</version>
<scope>runtime</scope>
</dependency>
Under the resources folder, create a folder named swagger, and then create an index.hbs file containing the following.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Swagger-ui</title>
<link rel="icon" type="image/png" href="https://unpkg.com/swagger-ui-dist@{{version}}/favicon-32x32.png">
<link rel="stylesheet" type="text/css" href="https://unpkg.com/swagger-ui-dist@{{version}}/swagger-ui.css">
<script src="https://unpkg.com/swagger-ui-dist@{{version}}/swagger-ui-standalone-preset.js"></script>
<script src="https://unpkg.com/swagger-ui-dist@{{version}}/swagger-ui-bundle.js"></script>
</head>
<body>
<div id="swagger-ui"></div>
<script>
window.onload = function() {
var ui = SwaggerUIBundle({
urls: [{{#each urls}}
{
name: "{{name}}",
url: "{{url}}"
}{{#unless @last}},{{/unless}}{{/each}}
],
dom_id: '#swagger-ui',
deepLinking: {{deepLinking}},
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "{{layout}}"
});
window.ui = ui
}
</script>
</body>
</html>
Finally, in the application main class, add the @OpenApiDefinition
annotation to enable the annotation processor to scan the entire appliaction.
@OpenAPIDefinition(
info = @Info(
title = "swagger-server",
version = "0.1",
description = "My API",
license = @License(name = "Apache 2.0")
)
)
public class Application {
public static void main(String[] args) {
Micronaut.run(Application.class);
}
}
A word of advice regarding the annotation processor as it stands in micronaut 1.0.0 is that public fields on an object will not be exposed, so you need to have getters/setters if you want to see the schema for the input or return values.
If you'd like to try out a running example of the above, I have a repo with the swagger server configuration located here https://github.com/frehov/micronaut-swagger-server which includes the ability to make a post with a list of url and name pairs to be rendered by Swagger.
Micronaut able to automatically generate Swagger YAML definitions from our controller and methods based on these annotations. Add swagger-annotations dependency pom.xml.
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-annotations</artifactId>
<version>2.0.5</version>
</dependency>
Add @OpenAPIDefinition annotation to application's main class.
@OpenAPIDefinition(
info = @Info(
title = "my app",
version = "1.0",
description = "my api",
contact = @Contact(url = "http://something.com", name = "something", email = "something")
)
)
public class Application {
public static void main(String[] args) {
Micronaut.run(Application.class);
}
}
Micronaut generates a Swagger file at target/classes/META-INF/swagger/my-app-1.0.yml. We can expose it outside the application using an HTTP endpoint. Here's the appropriate configuration provided inside the application.yml file.
micronaut:
router:
static-resources:
swagger:
paths: classpath:META-INF/swagger
mapping: /swagger/**
Accesspath http://localhost:8080/swagger/my-app-1.0.yml.
In comparison to Spring Boot, we don't have projects like Swagger SpringFox for Micronaut, so we need to copy the content to an online editor in order to see the graphical representation of our Swagger YAML.
Paste your content of my-app-1.0.yml to https://editor.swagger.io/ and add server to access Swagger UI.
Read Micronaut Doc- https://micronaut-projects.github.io/micronaut-openapi/latest/guide/index.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With