Block Image

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:

  1. there isn't the requirement to use @EnableSwagger2 annotation
  2. the documentation type is DocumentationType.OAS_30 and not DocumentationType.SWAGGER_2 anymore
  3. 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:

Block Image

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