Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Configuring Swagger UI with Spring Boot

I am trying to configure Swagger UI with my Spring boot application. Although the v2/api-docs seems to be loading properly, the http://localhost:8080/swagger-ui.html does not load my annotated REST API.

Here is what I have:

pom.xml:

...
<!--Swagger UI-->
        <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.4.0</version>
        </dependency>
...

SwaggerConfig.java

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import static springfox.documentation.builders.PathSelectors.regex;

@Configuration
@EnableSwagger2
public class SwaggerConfig
{
    @Bean
    public Docket api()
    {
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .apis(RequestHandlerSelectors.any())
                .paths(regex("/.*"))
                .build().apiInfo(apiInfo());
    }

    private ApiInfo apiInfo()
    {
        ApiInfo apiInfo = new ApiInfo(
                "My Project's REST API",
                "This is a description of your API.",
                "version-1",
                "API TOS",
                "[email protected]",
                "API License",
                "API License URL"
        );
        return apiInfo;
    }
}

http://localhost:8080/v2/api-docs:

{"swagger":"2.0","info":{"description":"This is a description of your API.","version":"version-1","title":"My Project's REST API","termsOfService":"API TOS","contact":{"name":"[email protected]"},"license":{"name":"API License","url":"API License URL"}},"host":"localhost:8080","basePath":"/","tags":[{"name":"test-controller","description":"Test Controller"},{"name":"custom-field-controller","description":"Custom Field Controller"},{"name":"user-controller","description":"User Controller"},{"name":"users-controller","description":"Users Controller"},{"name":"crudapi-controller","description":"CRUDAPI Controller"},{"name":"basic-error-controller","description":"Basic Error Controller"}],"paths":{"/":{"get":{"tags":["crudapi-controller"],"summary":"greeting","operationId":"greetingUsingGET","consumes":["application/json"],"produces":["*/*"],"responses":{"200":{"description":"OK","schema":{"type":"string"}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not Found"}}}},"/api/javainuse":{"get":{"tags":["test-controller"],"summary":"firstPage","operationId":"firstPageUsingGET","consumes":["application/json"],"produces":["*/*"],"responses":{"200":{"description":"OK","schema":{"type":"string"}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not Found"}}}},"/error":{"get":{"tags":["basic-error-controller"],"summary":"errorHtml","operationId":"errorHtmlUsingGET","consumes":["application/json"],"produces":["text/html"],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/ModelAndView"}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not Found"}}},"head":{"tags":["basic-error-controller"],"summary":"errorHtml","operationId":"errorHtmlUsingHEAD","consumes":["application/json"],"produces":["text/html"],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/ModelAndView"}},"401":{"description":"Unauthorized"},"204":{"description":"No Content"},"403":{"description":"Forbidden"}}},"post":{"tags":["basic-error-controller"],"summary":"errorHtml","operationId":"errorHtmlUsingPOST","consumes":["application/json"],"produces":["text/html"],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/ModelAndView"}},"201":{"description":"Created"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not Found"}}},"put":{"tags":["basic-error-controller"],"summary":"errorHtml","operationId":"errorHtmlUsingPUT","consumes":["application/json"],"produces":["text/html"],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/ModelAndView"}},"201":{"description":"Created"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not Found"}}},"delete":{"tags":["basic-error-controller"],"summary":"errorHtml","operationId":"errorHtmlUsingDELETE","consumes":["application/json"],"produces":["text/html"],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/ModelAndView"}},"401":{"description":"Unauthorized"},"204":{"description":"No Content"},"403":{"description":"Forbidden"}}},"options":{"tags":["basic-error-controller"],"summary":"errorHtml","operationId":"errorHtmlUsingOPTIONS","consumes":["application/json"],"produces":["text/html"],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/ModelAndView"}},"401":{"description":"Unauthorized"},"204":{"description":"No Content"},"403":{"description":"Forbidden"}}},"patch":{"tags":["basic-error-controller"],"summary":"errorHtml","operationId":"errorHtmlUsingPATCH","consumes":["application/json"],"produces":["text/html"],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/ModelAndView"}},"401":{"description":"Unauthorized"},"204":{"description":"No Content"},"403":{"description":"Forbidden"}}}},"/fields":{"get":{"tags":["custom-field-controller"],"summary":"greeting","operationId":"greetingUsingGET_1","consumes":["application/json"],"produces":["*/*"],"responses":{"200":{"description":"OK","schema":{"type":"string"}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not Found"}}}},"/fields/{id}":{"get":{"tags":["custom-field-controller"],"summary":"fieldAPIController","operationId":"fieldAPIControllerUsingGET","consumes":["application/json"],"produces":["*/*"],"parameters":[{"name":"id","in":"path","description":"id","required":true,"type":"integer","format":"int32"}],"responses":{"200":{"description":"OK","schema":{"type":"array","items":{"$ref":"#/definitions/CustomField"}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not Found"}}}},"/users":{"get":{"tags":["user-controller"],"summary":"greeting","operationId":"greetingUsingGET_2","consumes":["application/json"],"produces":["*/*"],"responses":{"200":{"description":"OK","schema":{"type":"string"}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not Found"}}}},"/users/":{"get":{"tags":["users-controller"],"summary":"listUsers","operationId":"listUsersUsingGET","consumes":["application/json"],"produces":["*/*"],"responses":{"200":{"description":"OK","schema":{"type":"array","items":{"$ref":"#/definitions/UserJPA"}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not Found"}}},"head":{"tags":["users-controller"],"summary":"listUsers","operationId":"listUsersUsingHEAD","consumes":["application/json"],"produces":["*/*"],"responses":{"200":{"description":"OK","schema":{"type":"array","items":{"$ref":"#/definitions/UserJPA"}}},"401":{"description":"Unauthorized"},"204":{"description":"No Content"},"403":{"description":"Forbidden"}}},"post":{"tags":["users-controller"],"summary":"listUsers","operationId":"listUsersUsingPOST","consumes":["application/json"],"produces":["*/*"],"responses":{"200":{"description":"OK","schema":{"type":"array","items":{"$ref":"#/definitions/UserJPA"}}},"201":{"description":"Created"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not Found"}}},"put":{"tags":["users-controller"],"summary":"listUsers","operationId":"listUsersUsingPUT","consumes":["application/json"],"produces":["*/*"],"responses":{"200":{"description":"OK","schema":{"type":"array","items":{"$ref":"#/definitions/UserJPA"}}},"201":{"description":"Created"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not Found"}}},"delete":{"tags":["users-controller"],"summary":"listUsers","operationId":"listUsersUsingDELETE","consumes":["application/json"],"produces":["*/*"],"responses":{"200":{"description":"OK","schema":{"type":"array","items":{"$ref":"#/definitions/UserJPA"}}},"401":{"description":"Unauthorized"},"204":{"description":"No Content"},"403":{"description":"Forbidden"}}},"options":{"tags":["users-controller"],"summary":"listUsers","operationId":"listUsersUsingOPTIONS","consumes":["application/json"],"produces":["*/*"],"responses":{"200":{"description":"OK","schema":{"type":"array","items":{"$ref":"#/definitions/UserJPA"}}},"401":{"description":"Unauthorized"},"204":{"description":"No Content"},"403":{"description":"Forbidden"}}},"patch":{"tags":["users-controller"],"summary":"listUsers","operationId":"listUsersUsingPATCH","consumes":["application/json"],"produces":["*/*"],"responses":{"200":{"description":"OK","schema":{"type":"array","items":{"$ref":"#/definitions/UserJPA"}}},"401":{"description":"Unauthorized"},"204":{"description":"No Content"},"403":{"description":"Forbidden"}}}},"/users/{id}":{"get":{"tags":["user-controller"],"summary":"userAPIController","operationId":"userAPIControllerUsingGET","consumes":["application/json"],"produces":["*/*"],"parameters":[{"name":"id","in":"path","description":"id","required":true,"type":"integer","format":"int32"}],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/Collection«UserJPA»"}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not Found"}}}}},"definitions":{"UserJPA":{"type":"object"},"Collection«UserJPA»":{"type":"object"},"ModelAndView":{"type":"object","properties":{"empty":{"type":"boolean"},"model":{"type":"object"},"modelMap":{"type":"object","additionalProperties":{"type":"object"}},"reference":{"type":"boolean"},"status":{"type":"string","enum":["100","101","102","103","200","201","202","203","204","205","206","207","208","226","300","301","302","303","304","305","307","308","400","401","402","403","404","405","406","407","408","409","410","411","412","413","414","415","416","417","418","419","420","421","422","423","424","426","428","429","431","451","500","501","502","503","504","505","506","507","508","509","510","511"]},"view":{"$ref":"#/definitions/View"},"viewName":{"type":"string"}}},"CustomField":{"type":"object","properties":{"name":{"type":"string"}}},"View":{"type":"object","properties":{"contentType":{"type":"string"}}}}}

The swagger-ui.html (http://localhost:8080/swagger-ui.html) does not show the expected REST calls: enter image description here

The error in swagger-ui.html from the code inspection: Failed to load resource: the server responded with a status of 404 ().

I have googled around (tried web-config mvc too) but the error persists. Maybe I am missing a resource reference in the .iml file?

like image 647
Menelaos Kotsollaris Avatar asked Apr 26 '17 18:04

Menelaos Kotsollaris


People also ask

How do I enable Swagger configuration in spring boot?

To enable the Swagger2 in Spring Boot application, you need to add the following dependencies in our build configurations file. For Gradle users, add the following dependencies in your build. gradle file. Now, add the @EnableSwagger2 annotation in your main Spring Boot application.

What is the URL for Swagger UI in spring boot?

http://localhost:8080/your-app-root/swagger-ui/ In our case, by the way, the exact URL will be: http://localhost:8080/spring-security-rest/api/swagger-ui/

Can we customize Swagger UI?

By default, Swagger UI uses BaseLayout , which is built into the application. You can specify a different layout to be used by passing the layout's name as the layout parameter to Swagger UI. Be sure to provide your custom layout as a component to Swagger UI.


2 Answers

I had this issue today and fixed it by matching up the versions of my springfox-swagger2 and springfox-swagger-ui 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>

There's very little other code to just get it up and running. One simple config class:

@Configuration
@EnableSwagger2
class SwaggerConfiguration {

    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.foo.samples.swaggersample"))
                .paths(PathSelectors.any())
                .build();
    }

}

And my application.properties

# location of the swagger json
springfox.documentation.swagger.v2.path=/swagger.json

(This is in Spring Boot).

like image 178
Paul J Avatar answered Sep 19 '22 22:09

Paul J


Statement : Generate Swagger UI for the listing of all the REST APIs through Spring Boot Application.

Follow the below steps to generate the Swagger UI through Spring Boot application:

1. Add following dependency in pom.xml –

    <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>

2. Add the following piece of code in your main application class having the @EnableSwagger2 annotation.

    @EnableSwagger2
    @SpringBootApplication
    public class MyApp {
    public static void main(String[] args) {
        SpringApplication.run(MyApp.class, args);
    }

    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2).select()  
           .apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
           .paths(PathSelectors.any()).build().pathMapping("/")
           .apiInfo(apiInfo()).useDefaultResponseMessages(false);
    }

    @Bean
    public ApiInfo apiInfo() {
        final ApiInfoBuilder builder = new ApiInfoBuilder();
        builder.title("My Application API through Swagger UI").version("1.0").license("(C) Copyright Test")
        .description("List of all the APIs of My Application App through Swagger UI");
        return builder.build();
        }
    }

3. Add the below RootController class in your code to redirect to the Swagger UI page. In this way, you don’t need to put the dist folder of Swagger-UI in your resources directory.

    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    @Controller
    @RequestMapping("/")
    public class RootController {
        @RequestMapping(method = RequestMethod.GET)
        public String swaggerUi() {
            return "redirect:/swagger-ui.html";
        }
    }

4. Being the final steps, add the @Api and @ApiOperation notation in all your RESTControllers like below –

    import static org.springframework.web.bind.annotation.RequestMethod.GET;
    import org.springframework.http.HttpStatus;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.ResponseStatus;
    import org.springframework.web.bind.annotation.RestController;
    import io.swagger.annotations.Api;
    import io.swagger.annotations.ApiOperation;

    @RestController
    @RequestMapping("/hello")
    @Api(value = "hello", description = "Sample hello world application")
    public class TestController {

        @ApiOperation(value = "Just to test the sample test api of My App Service")
        @RequestMapping(method = RequestMethod.GET, value = "/test")
        // @Produces(MediaType.APPLICATION_JSON)
        public String test() {
            return "Hello to check Swagger UI";
        }

        @ResponseStatus(HttpStatus.OK)
        @RequestMapping(value = "/test1", method = GET)
        @ApiOperation(value = "My App Service get test1 API", position = 1)
        public String test1() {
            System.out.println("Testing");
            if (true) {
                return "Tanuj";
            }
            return "Gupta";
        }
    }

Now your are done. Now to run your Spring Boot Application, go to browser and type localhost:8080. You will see Swagger UI having all the details of your REST APIs.

Happy Coding. 🙂
The source code of the above implementation is also on my blog if you feel like checking it out.

like image 37
user2014334 Avatar answered Sep 20 '22 22:09

user2014334