Getting swagger-ui to display my codegen-generated API - spring-boot

I'm working on a springboot project. We're doing API first so we're generating code from an api.yaml. We're using openapi 3.0. The interfaces are being generated fine but when we browse to our swagger-ui URL, it says No operations defined in spec!
Here are the details:
#Configuration
#RequiredArgsConstructor
#EnableSwagger2
public class SwaggerConfig {
private final BuildProperties buildProperties;
#Bean
public Docket docketConfig() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors
.basePackage("com.xyz.infrastructure.rest.spring.resource"))
.build().apiInfo(apiInfo());
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title(buildProperties.getName())
.version(buildProperties.getVersion())
.build();
}
}
Our structure is:
com.xyz.infrastructure.rest.spring
|
|- config
|- SwaggerConfig
|- spec //autogenerated
|- dto //autogenerated
|- resource // implementations of interfaces found in spec
What are we missing?
We're using:
<dependency>
<groupId>io.swagger.codegen.v3</groupId>
<artifactId>swagger-codegen</artifactId>
<version>3.0.21</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
Thank you!

We finally got it to work. Here's what did it for us:
Springfox version 3:
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
Using the io.swagger.codegen.v3 plugin.
This swagger config:
#Configuration
#EnableOpenApi
public class SwaggerConfig {
#Bean
public Docket docketConfig() {
return new Docket(DocumentationType.OAS_30)
.select()
.apis(RequestHandlerSelectors
.basePackage("com.xyz.infrastructure.rest.spring.resource"))
.build();
}
}
And make sure your classes in resource have the #RestController annotation.

I used like below:
#Configuration
#EnableSwagger2
public class SwaggerConfig extends WebMvcConfigurationSupport {
#Bean
public Docket productApi() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
//.apis(RequestHandlerSelectors.any())
.apis(RequestHandlerSelectors.basePackage("uz.xb.qr_project"))//*** base package
.paths(PathSelectors.any())
.build()
.apiInfo(metaData());
}
private ApiInfo metaData() {
return new ApiInfoBuilder()
.title("Spring Boot REST API")
.description("\"Spring Boot REST API for Online Store\"")
.version("1.0.0")
.license("Apache License Version 2.0")
.licenseUrl("https://www.apache.org/licenses/LICENSE-2.0\"")
.contact(new Contact("John Thompson", "https://springframework.guru/about/", "john#springfrmework.guru"))
.build();
}
#Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html")//**address of swagger ui
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
}
}
ApiController.java
#RestController
#RequestMapping
public class ApiController {
#Autowired
private ApiService apiService;
#GetMapping
public String swagger(){
return "<!DOCTYPE html>\n" +
"<html lang=\"en\">\n" +
"<head>\n" +
" <meta charset=\"UTF-8\">\n" +
" <title>REST API LIST</title>\n" +
" <meta http-equiv=\"refresh\" content=\"0; url=/qr_online/swagger-ui.html\" />\n" +
"</head>\n" +
"<body>\n" +
"REST API LIST\n" +
"</body>\n" +
"</html>";
}
//Or you can use like this inside controller
/*
#GetMapping
public void redirect(HttpServletResponse response) throws IOException {
response.sendRedirect("swagger-ui.html");
}
*/
}
pom.xml
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>

Related

After deploy in jenkins, i can't find swagger

Actually, after i deployed my project on jenkins, i can't find swagger api docs.
what if our domain xxx.oooo.com, i've tried "xxx.oooo.com/swagger-ui/index.html", but can't still find. Also i tried ip4 address as well. but still doesn't work.
there is no problem about deploy, because there is no fail on jenkins.
i didnt work for front-end side, so i have no idea, but is it possible to be related with front-end about unable finding swagger api docs?..
i've also tried a lot of times through google, but still couldn't find answer yet. Plus, it works on local server really well!
here is my swaggerConfig.java file.
#Configuration
#EnableSwagger2
public class SwaggerConfig extends WebMvcConfigurationSupport {
#Value("${swagger.info.title}")
private String title;
#Value("${swagger.info.desc}")
private String desc;
#Value("${swagger.info.version}")
private String version;
#Bean
public Docket api() {
return new Docket(DocumentationType.OAS_30)
.securityContexts(Arrays.asList(securityContext()))
.securitySchemes(Arrays.asList(apiKey()))
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.company.controller"))
.paths(PathSelectors.any())
.build();
}
public ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title(title)
.description(desc)
.version(version)
.build();
}
public SecurityContext securityContext() {
return SecurityContext.builder()
.securityReferences(defaultAuth())
.build();
}
public List<SecurityReference> defaultAuth() {
AuthorizationScope authorizationScope = new AuthorizationScope("global", "accept all");
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
authorizationScopes[0] = authorizationScope;
return Arrays.asList(new SecurityReference("Authorization", authorizationScopes));
}
public ApiKey apiKey() {
return new ApiKey("Authorization", "Authorization", "header");
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/swagger-ui/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/");
}
}
I am using
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>3.0.0</version>
</dependency>
I also set up webConfig as well.
#Configuration
public class WebConfig implements WebMvcConfigurer {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*");
}
}

Have a problem with swagger-ui and springboot

this is the configuration and the dependencies i use :
<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 this is the configuration:
#Configuration
#EnableSwagger2
public class SwaggerConfig {
public static final Contact DEFAULT_CONTACT = new Contact(
"test", "https://www.test.com", "contact#mycode.ma");
public static final ApiInfo DEFAULT_API_INFO = new ApiInfo(
"test api", "For signing pdf document", "1.0",
"urn:tos", DEFAULT_CONTACT,
"License", "license 0-1");
private static final Set<String> DEFAULT_PRODUCES_AND_CONSUMES =
new HashSet<String>(Arrays.asList("application/json",
"application/xml"));
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(DEFAULT_API_INFO)
.produces(DEFAULT_PRODUCES_AND_CONSUMES)
.consumes(DEFAULT_PRODUCES_AND_CONSUMES);
}
}
And when i use this path : http://localhost:8090/v2/api-docs gives me the json.
but when i want to use http://localhost:8090/swagger-ui.html doesn't work.
thank your for helping me.
Try extending WebMvcConfigurationSupport as shown in below and override add ResourceHandlers and should work for you.
#Configuration
#EnableSwagger2
public class SwaggerConfig extends WebMvcConfigurationSupport {
public static final Contact DEFAULT_CONTACT = new Contact("Nagaraja", "", "email-id");
private static final Set<String> DEFAULT_PRODUCES_AND_CONSUMES = new HashSet<>(
Arrays.asList("application/json"));
#Bean
public Docket productApi() {
return new Docket(DocumentationType.SWAGGER_2).apiInfo(metaData()).produces(DEFAULT_PRODUCES_AND_CONSUMES)
.consumes(DEFAULT_PRODUCES_AND_CONSUMES).select()
.apis(RequestHandlerSelectors.basePackage("controller-package")).paths(PathSelectors.any())
.build();
}
private ApiInfo metaData() {
return new ApiInfoBuilder().title("REST API")
.description("Write description").version("1.0.0")
.license("Apache License Version 2.0").licenseUrl("https://www.apache.org/licenses/LICENSE-2.0")
.contact(DEFAULT_CONTACT).build();
}
#Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
Maven dependencies:
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.8.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.8.0</version>
<scope>compile</scope>
</dependency>

swagger not detected when i remove #configuration

i try to integrate swagger into my spring boot project but i receive always an error :
"Error creating bean with name 'modelMapperImpl': Failed to introspect bean class [springfox.documentation.swagger2.mappers.ModelMapperImpl] " but when i remove #configuration from swaggerConfig swagger will not be detected ,here is my code :
WebConfig:
#Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedMethods("HEAD", "GET", "PUT", "POST", "DELETE",
"PATCH");
}
}
SwaggerConfig
#EnableSwagger2
#Configuration
public class SwaggerConfig {
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build();
}
}
Pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.7.0</version>
</dependency>
Try this approach.
#Configuration
#ConfigurationProperties(prefix = "mycompany.cors")
public class CorsSettings {
final private Logger log = LoggerFactory.getLogger(CorsSettings.class);
private List<String> origins = new ArrayList<>();
public CorsSettings() {
log.debug("construct CorsSettings");
}
public List<String> getOrigins() {
return this.origins;
}
#Bean
public WebMvcConfigurer corsConfigurer() {
if (origins != null) {
log.debug("corsOrgins=" + origins);
} else {
log.error("corsOrgins=null");
}
return new WebMvcConfigurerAdapter() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins(origins.toArray(new String[origins.size()]));
}
};
}
}
Next in Config
#Configuration
public class SwaggerConfig {
ApiInfo apiInfo() {
return new ApiInfoBuilder().title("My Swagger API").description("This is a my swagger server")
.license("").licenseUrl("https://opensource.org/licenses/MIT").termsOfServiceUrl("").version("1.0.0")
.contact(new Contact("My name", "://www.mycompany.com", "myemail#mycompany.com"))
.build();
}
#Bean
public Docket customImplementation() {
return new Docket(DocumentationType.SWAGGER_2).select()
.apis(RequestHandlerSelectors.basePackage("com.mycompany.path")).build()
.apiInfo(apiInfo());
}
}
Then in application.yml
mycompany:
cors:
origins:
- ${origin1:http://localhost:8080}
- ${origin2:http://localhost:8080}
- ${origin3:http://localhost:8080}
- ${origin4:http://localhost:8080}

springfox-data-rest configuration not work

I follow the link to config.
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-data-rest</artifactId>
<version>2.7.0</version>
</dependency>
#Configuration
#Import( {springfox.documentation.spring.data.rest.configuration.SpringDataRestConfiguration.class})
public class WebMvcConfig extends WebMvcConfigurerAdapter{
......
}
#RepositoryRestResource(collectionResourceRel = "mails", path = "mails")
public interface TMessageMailDao extends PagingAndSortingRepository<TMessageMail, Long>{
}
But when I open http://localhost:8080/swagger-ui.html, there is nothing.
I know springfox-data-rest is still in incubation. Is that the reason it's not work? Or anything wrong?
You are missing #EnableSwagger2 annotation.
Make sure to create a Docket bean as shown in the example below.
#Configuration
#Import({SpringDataRestConfiguration.class})
#EnableSwagger2
public class WebMvcConfig extends WebMvcConfigurerAdapter {
...
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("example")
.select()
.paths(PathSelectors.any())
.build()
.apiInfo(apiInfo("Example API", "Example API"));
}
private ApiInfo apiInfo(String title, String description) {
return new ApiInfoBuilder()
.title(title)
.description(description)
.build();
}
}
Make sure to add the following dependencies:
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.7.0</version>
</dependency>
Once it's working, your swagger-ui.html will look something like this:
I want to scan two packages. How to include two base packages and not one?
Just Controllers
If you are just interested in including REST controllers and not any repository, you can specify any number of packages within apis method of Docket with the help of a custom method.
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("book")
.select()
.apis(exactPackages("com.basaki.controller", "com.basaki.model"))
.paths(PathSelectors.any())
.build()
.apiInfo(apiInfo("Example Springfox API",
"Example Springfox API"));
}
private static Predicate<RequestHandler> exactPackages(
final String... pkgs) {
return input -> {
String currentPkg =
input.declaringClass().getPackage().getName();
for (String pkg : pkgs) {
if (pkg.equals(currentPkg)) {
return true;
}
}
return false;
};
}
Controllers and Repositories
If you are interested in including REST controllers and repositories, you have to take advantage of paths method in Docket with the help of a custom method. The custom method takes path regexes.
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("book")
.select()
.paths(matchPathRegex("/books(/|$).*",
"/booxs(/|$).*", "/tokens(/|$).*",
"/ping(/|$).*"))
.build()
.apiInfo(apiInfo("Example Springfox API",
"Example Springfox API"));
}
private static Predicate<String> matchPathRegex(final String... pathRegexs) {
return new Predicate<String>() {
#Override
public boolean apply(String input) {
for (String pathRegex : pathRegexs) {
if (input.matches(pathRegex)) {
return true;
}
}
return false;
}
};
}
Thank you for Indra Basak 's help.
My configuration just have one problem.
#Configuration
#EnableSwagger2
#Import({SpringDataRestConfiguration.class})
This three annotations have to use together. I config #EnableSwagger2 in another configuration file.

Swagger UI does not show all the controllers of my project

I have few controllers which have the same request path prefix i.e.
/v4/users/{userId}/
And then the methods in the controllers are annotated with separate path mappings. The swagger ui shows only one of those controllers.
#Component
public class BaseController {
}
/******************/
#RestController
#RequestMapping("/v4/users/{userId}/payment")
public class PaymentController extends BaseController {
#RequestMapping(value = "/initiate", method = RequestMethod.POST)
public HttpEntity<Object> initiatePayment() {...}
#RequestMapping(value = "/success", method = RequestMethod.GET)
public HttpEntity<Object> success() {...}
}
#RestController
#RequestMapping("/v4/users/{userId}/preferences")
public class CustomerPreferencesController extends BaseController{
#RequestMapping(value = "/deals/{dealId}", method = RequestMethod.POST)
public HttpEntity<Object> favouriteDeal(...) {...}
//some more methods
}
There is one more controller that has the same path prefix i.e. /v4/users/{userId} which shows up on swagger-ui but not the above two controllers.
pom.xml entries:
<!-- Swagger Spring -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.0.2</version>
</dependency>
UPDATE - 1
#Bean
public Docket mobileAPI() {
return new Docket(DocumentationType.SWAGGER_2)
.host(swaggerHost)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build()
.apiInfo(apiInfo())
.pathMapping("/");
}

Resources