The Swagger 3 version of the springfox's library gives a lot of changes, including a simple
integration with OpenAPI.
OpenAPI is a specification that allows to standardise the API REST representation.
Step 1: let's import this dependency
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
If you migrated from Swagger 2, you have to remove the other dependencies. This dependency in fact allows integrating swagger, its ui and the Spring Data Rest API.
Step 2: write a Swagger configuration class
@Configuration
public class SwaggerConfig {
@Bean
public Docket api() {
return new Docket(DocumentationType.OAS_30)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build()
.forCodeGeneration(true);
}
}
We can highlight 3 points:
- there isn't the requirement to use @EnableSwagger2 annotation
- the documentation type is DocumentationType.OAS_30 and not DocumentationType.SWAGGER_2 anymore
- the forCodeGeneration method allows to have a right formatting of the swagger documentation for
autogenerate the client without to find problems of characters
Step 3: let's try the Swagger UI from the browser
Compared to swagger 2, the default endpoint isn't /swagger-ui.html anymore but /swagger-ui/.
For the sake of simplicity I used a project of a previous tutorial: Spring Boot REST
who has a User entity with a JpaRepository that is da API Resource too.
Going to http://localhost:8080/swagger-ui/ we obtain a screen like this:
If we go to http://localhost:8080/v3/api-docs we can read the documentation of our API that follows OpenAPI specification:
{
"openapi": "3.0.3",
"info": {
"title": "Api Documentation",
"description": "Api Documentation",
"termsOfService": "urn:tos",
"contact": {},
"license": {
"name": "Apache 2.0",
"url": "http://www.apache.org/licenses/LICENSE-2.0"
},
"version": "1.0"
},
"servers": [
{
"url": "http://localhost:8080",
"description": "Inferred Url"
}
],
"tags": [
{
"name": "User Entity",
"description": "Simple Jpa Repository"
}
],
...
Self-generating of a REST client from Swagger
Step 1: let's add this plugin in the pom:
<profiles>
<profile>
<id>rest-client</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<version>4.3.1</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>${project.basedir}/swagger.json</inputSpec>
<generatorName>java</generatorName>
<skipValidateSpec>true</skipValidateSpec>
<configOptions>
<sourceFolder>src/gen/java/main</sourceFolder>
</configOptions>
<generateApiTests>false</generateApiTests>
<generateModelTests>false</generateModelTests>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>logging-interceptor</artifactId>
<version>4.8.1</version>
</dependency>
<dependency>
<groupId>org.threeten</groupId>
<artifactId>threetenbp</artifactId>
<version>1.4.1</version>
</dependency>
<dependency>
<groupId>io.gsonfire</groupId>
<artifactId>gson-fire</artifactId>
<version>1.8.4</version>
</dependency>
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<version>3.0.2</version>
</dependency>
</dependencies>
</profile>
</profiles>
Step 2: let's add the swagger.json file
Inside the root project directory, let's create the swagger.json file. We can copy the response of http://localhost:8080/v3/api-docs inside the file. Alternatively, we can self-generate the file in several ways; here I wrote a test class to generate the file:
package it.enzoracca.springbootapp;
import com.fasterxml.jackson.databind.JsonNode;
import jdk.nashorn.internal.ir.annotations.Ignore;
import org.apache.commons.io.FileUtils;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import java.io.File;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@Ignore
public class SwaggerGenerator {
@Autowired
private TestRestTemplate testRestTemplate;
@Test
public void generateSwagger() throws Exception {
JsonNode response = testRestTemplate.getForObject("http://localhost:8080/v3/api-docs", JsonNode.class);
FileUtils.writeStringToFile(new File("swagger.json"), response.toPrettyString());
}
}
In this class I used apache-commons' FileUtils, adding this maven dependency:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
</dependency>
Once create the file, we build the project with: mvn clean install -Prest-client.
After we build the project, we can find inside of
target/generated-sources/openapi/src/gen/java/main/api the autogenerated api client.
For example, having a UserEntity resource (that is the APIs of UserRepository) in the project,
we'll find a UserEntityApi class with the relative methods.
Moreover, in the target/generated-sources/openapi/api we'll find the autogenerated openapi.yaml file.
Step 3: let's try the client
For the sake of simplicity, for to try the autogenerated client, we create a client subpackage inside the project with this class:
public class ClientDemo {
public static void main(String... args) throws ApiException {
UserEntityApi userEntityApi = new UserEntityApi();
User user = new User();
user.setName("Mario");
user.setSurname("Rossi");
EntityModelOfUser userRet = userEntityApi.saveUserUsingPOST(user);
System.out.println("UTENTE INSERITO: " + userRet);
CollectionModelOfUser allUsers = userEntityApi.findAllUserUsingGET(null, null, null);
System.out.println("GET ALL: " + allUsers);
}
}
We'll have to similar output:
UTENTE INSERITO: class EntityModelOfUser {
address: null
id: null
links: null
name: Mario
surname: Rossi
}
GET ALL: class CollectionModelOfUser {
embedded: class EmbeddedCollectionOfUser {
users: [class User {
address: null
id: null
name: Mario
surname: Rossi
}]
}
links: {self=class Link {
deprecation: null
href: http://localhost:8080/users
hreflang: null
media: null
name: null
profile: null
rel: null
title: null
type: null
}, profile=class Link {
deprecation: null
href: http://localhost:8080/profile/users
hreflang: null
media: null
name: null
profile: null
rel: null
title: null
type: null
}}
}
Conclusions
In few steps, we have imported/updated Swagger with the version 3, and the OpenAPI specification, and we have self-generating a REST client.
You can download the full project from my github in this link: Spring Boot OpenAPI
Posts of Spring Framework: Spring
Recommended books about Spring:
- Pro Spring 5 (Spring from scratch a hero): https://amzn.to/3KvfWWO
- Pivotal Certified Professional Core Spring 5 Developer Exam: A Study Guide Using Spring Framework 5 (for Spring certification): https://amzn.to/3KxbJSC
- Pro Spring Boot 2: An Authoritative Guide to Building Microservices, Web and Enterprise Applications, and Best Practices (Spring Boot of the detail): https://amzn.to/3TrIZic