OpenAPI Specification (formerly Swagger Specification)
Auto generate documentation for your REST API, is a great way to document and it's auto generated and finally you follows a specification, that people have thought throw.
OpenAPI (part of Eclise Microprofile) Annotation
Maven dependency.
<dependency>
<groupId>org.eclipse.microprofile</groupId>
<artifactId>microprofile</artifactId>
<version>3.0</version>
<type>pom</type>
<scope>provided</scope>
</dependency>
And annotated Java code.
package se.magnuskkarlsson.example_openapi_swagger.boundary;
import java.util.ArrayList;
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import org.eclipse.microprofile.openapi.annotations.Operation;
import org.eclipse.microprofile.openapi.annotations.enums.SchemaType;
import org.eclipse.microprofile.openapi.annotations.media.Content;
import org.eclipse.microprofile.openapi.annotations.media.Schema;
import org.eclipse.microprofile.openapi.annotations.parameters.Parameter;
import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
import org.eclipse.microprofile.openapi.annotations.responses.APIResponses;
import se.magnuskkarlsson.example_openapi_swagger.entity.Person;
@Path("/persons")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class PersonResource {
@GET
@Operation(summary = "Get all persons.", description = "Get all persons in DB.")
@APIResponses(value = { //
@APIResponse( //
responseCode = "500", //
description = "Internal Error", //
content = @Content(mediaType = MediaType.APPLICATION_JSON)),
@APIResponse( //
responseCode = "200", //
description = "All persons in DB.", //
content = @Content( //
mediaType = MediaType.APPLICATION_JSON, //
schema = @Schema(implementation = Person.class))) })
public List<Person> search( //
@Parameter( //
description = "The name to search for.", //
required = false, //
example = "*he*", //
schema = @Schema(type = SchemaType.STRING)) //
@QueryParam("name") String name) {
var persons = new ArrayList<Person>();
var person1 = new Person().setName("FOO").setAge(24);
persons.add(person1);
var person2 = new Person().setName("BAR").setAge(51);
persons.add(person2);
return persons;
}
}
And maven plugin, which will auto generate OpenAPI specification and output in YAML file in your webapp root folder.
<!-- https://github.com/kongchen/swagger-maven-plugin -->
<plugin>
<groupId>com.github.kongchen</groupId>
<artifactId>swagger-maven-plugin</artifactId>
<version>3.1.8</version>
<configuration>
<apiSources>
<apiSource>
<springmvc>false</springmvc>
<locations>se.magnuskkarlsson.example_openapi_swagger.boundary</locations>
<!-- <schemes>http</schemes> <host>localhost:8081</host> -->
<basePath>/${project.build.finalName}</basePath>
<info>
<title>Users API</title>
<version>v1</version>
<description>Users rest endpoints</description>
</info>
<outputFormats>yaml</outputFormats>
<swaggerDirectory>${basedir}/src/main/webapp</swaggerDirectory>
</apiSource>
</apiSources>
</configuration>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
</dependencies>
</plugin>
Reference:
- Eclipse MicroProfile
- Eclipse MicroProfile OpenAPI Homepage at GitHub
- OpenAPI Specificiation (master version)
- Swagger Maven Plugin
Generated OpenAPI YAML Specification
---
swagger: "2.0"
info:
description: "Users rest endpoints"
version: "v1"
title: "Users API"
basePath: "/example-openapi-swagger-1.0.0-SNAPSHOT"
paths:
/persons:
get:
operationId: "search"
consumes:
- "application/json"
produces:
- "application/json"
parameters:
- name: "name"
in: "query"
required: false
type: "string"
responses:
200:
description: "successful operation"
schema:
type: "array"
items:
$ref: "#/definitions/Person"
definitions:
Person:
type: "object"
properties:
name:
type: "string"
age:
type: "integer"
format: "int32"
Complete pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>se.magnuskkarlsson</groupId>
<artifactId>example-openapi-swagger</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.build.outputEncoding>UTF-8</project.build.outputEncoding>
<failOnMissingWebXml>false</failOnMissingWebXml>
<bouncycastle.version>1.65</bouncycastle.version>
<hibernate.version>5.3.14.Final</hibernate.version>
<hibernate-validator.version>6.0.18.Final</hibernate-validator.version>
<primefaces.version>10.0.0</primefaces.version>
</properties>
<dependencies>
<!-- Java EE 8 -->
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>8.0</version>
<scope>provided</scope>
</dependency>
<!-- JBoss EAP 7.3 -->
<dependency>
<groupId>org.eclipse.microprofile</groupId>
<artifactId>microprofile</artifactId>
<version>3.0</version>
<type>pom</type>
<scope>provided</scope>
</dependency>
<!-- Test Support -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
<version>2.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.10.19</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.javafaker</groupId>
<artifactId>javafaker</artifactId>
<version>0.17.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.199</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.17</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-envers</artifactId>
<version>${hibernate.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>${hibernate-validator.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>jakarta.el</artifactId>
<version>3.0.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<release>11</release>
<showDeprecation>true</showDeprecation>
<showWarnings>true</showWarnings>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<!-- https://github.com/kongchen/swagger-maven-plugin -->
<plugin>
<groupId>com.github.kongchen</groupId>
<artifactId>swagger-maven-plugin</artifactId>
<version>3.1.8</version>
<configuration>
<apiSources>
<apiSource>
<springmvc>false</springmvc>
<locations>se.magnuskkarlsson.example_openapi_swagger.boundary</locations>
<!-- <schemes>http</schemes> <host>localhost:8081</host> -->
<basePath>/${project.build.finalName}</basePath>
<info>
<title>Users API</title>
<version>v1</version>
<description>Users rest endpoints</description>
</info>
<outputFormats>yaml</outputFormats>
<swaggerDirectory>${basedir}/src/main/webapp</swaggerDirectory>
</apiSource>
</apiSources>
</configuration>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>