Unable to add application name to base URL after adding swagger3 in my Springboot project - spring-boot

When I was using springfox-swagger 2.9.0, I was using below code in my project.
#Configuration
#EnableSwagger2
public class SwaggerConfig {
#Bean
public Docket api() {
Docket docket = null;
try{
if(!(profile.contains("local")|| (profile.contains("test"))
docket = new Docket(DocumentationType.SWAGGER_2)
.host(host)
.pathProvider(new RelativePathProvider(servletContext){
#Override
public String getApplicationBasePath(){
return "/api";
}
})
.select()
.apis(RequestHandlerSelectors.basePackage("org.app.controller"))
.paths(PathSelectors.any())
.build();
}
else{
docket = new Docket(DocumentationType.SWAGGER_2)
.host(host)
.select()
.apis(RequestHandlerSelectors.basePackage("org.app.controller"))
.paths(PathSelectors.any())
.build();
}
}
catch(Exception e){
logger.info("Unable to return docket",ex)
}
return docket;
}
}
After adding below swagger 3.0.0 dependency, my updated class is:
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
#Configuration
public class SwaggerConfig {
#Bean
public Docket api() {
Docket docket = null;
try{
if(!(profile.contains("local")|| (profile.contains("test"))
docket = new Docket(DocumentationType.SWAGGER_2)
.host(host)
.pathProvider(new PathProvider(){
#Override
public String getOperationPath(String operationPath){
return operationPath.replace("/api","");
}
#Override
public String getResourceListingPath(String groupName, String apiDeclaration){
return null;
}
})
.select()
.apis(RequestHandlerSelectors.basePackage("org.app.controller"))
.paths(PathSelectors.any())
.build();
}
else{
docket = new Docket(DocumentationType.SWAGGER_2)
.host(host)
.select()
.apis(RequestHandlerSelectors.basePackage("org.app.controller"))
.paths(PathSelectors.any())
.build();
}
}
catch(Exception e){
logger.info("Unable to return docket",ex)
}
return docket;
}
}
After using this code , I am not able to append "/api" to my baseurl "localhost:8080" from updated swagger url.
http://localhost:8080/abc-api/swagger-ui/index.html#/
The base url should appear as "localhost:8080/api".
I tried creating separate bean for PathProvider implementation and then passed in argument but still same issue is there.
Could anyone please tell me what am I doing wrong here and how to create the baseurl as "/api" instead or "/" ?

This is not an answer to your problem but it might help you.
Since you are migrating anyway, consider using springdoc instead of Springfox. It is a newer library that is easier to use and way less error-prone than Springfox. We moved to it 2 years ago and we are very glad we did. There is very good documentation and tutorials online for it:
https://springdoc.org/
https://www.baeldung.com/spring-rest-openapi-documentation
It is also very active and you usually get your issues answered very fast on the github page.

Related

swagger with spring webflux cannot find Publisher«ResponseEntity«object»»

I am trying to use swagger with spring webflux, but for some reason it gives an error message
Could not resolve reference because of: Could not resolve pointer:
/definitions/Publisher«ResponseEntity«object»» does not exist in
document
here it is the sawagger config
#Configuration
#EnableSwagger2WebFlux
public class SwaggerConfig {
private final SwaggerDocketBuilder builder;
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Reactive Documentation")
.description("Reactive API Documentation")
.version("1.0.0")
.build();
}
#Bean
public Docket docket() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(this.apiInfo())
.enable(true)
.select()
.paths(PathSelectors.any())
.build();
}
}
Found the answer
I have added .genericModelSubstitutes(Mono.class, Flux.class, Publisher.class);
the new docket()
#Bean
public Docket docket() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(this.apiInfo())
.enable(true)
.select()
.paths(PathSelectors.any())
.build()
.genericModelSubstitutes(Mono.class, Flux.class, Publisher.class);
}

Add context path to requests in swagger

I have an eureka service which has a swagger. The eureka is on http://localhost:8050
and the service goes by name /service. The issue is that when i open swagger and try to make a request, it sends it to http://localhost:8050/service/somecontroller. The service has a context path "path" so it should be http://localhost:8050/service/path/somecontroller. This is the configuration of the swagger:
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2).select()
.apis(RequestHandlerSelectors.basePackage("com.test")).paths(PathSelectors.any())
.build();
}
Springfox has an open issue (#2817) for your case, you can try one of the workarounds proposed by some users there.
Managed to change the context path of the swagger like this:
#Value("${contextPath}")
private String contextPath;
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
//.host(retrieveHostHostname())
.pathProvider(new PathProvider() {
#Override
public String getApplicationBasePath() {
return contextPath;
}
#Override
public String getOperationPath(String s) {
return s.replace("somecontroller", contextPath+"/somecontroller");
}
#Override
public String getResourceListingPath(String s, String s1) {
return "/";
}
}).select()
.apis(RequestHandlerSelectors.basePackage("com.test")).paths(PathSelectors.any())
.build();
}

How to pattern match of a API while exposing to Swagger2 in Spring Boot?

Below is the controller for which I need to write swagger2 API documents:
#RestController
#RequestMapping("/abc/def/pqr")
public class Controller {
#GetMapping(path = "", consumes = "application/json", produces = "application/json")
#ResponseBody
public <T> PagedResources<SomeResource> get(Pageable pageable,
Assembler assembler) {
Page<Something> somethings = service.get(pageable);
return pagedAssembler.toResource(somethings, assembler);
}
}
Below is the code for through which I am trying to write swagger to API documentations:
#Bean
public Docket swaggerConfiguration() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.paths(PathSelectors.ant("/abc/def/pqr/"))
.build()
}
But even after writing it, this API is not exposing to swagger2. Wherever, I can understand the problem I thing that there is some problem in PathSelectors.ant("/abc/def/pqr/") . So, please someone can help me then it's better for me.
Thanks in advance...
Try this
#Configuration
#EnableSwagger2
public class SwaggerConfig {
#Bean
public Docket productApi() {
return new Docket(DocumentationType.SWAGGER_2)
.select() .apis(RequestHandlerSelectors.basePackage("your.base.package"))
.paths(regex("/product.*"))
.build();
}
}

springboot Multiple Dockets with the same group name are not supported

I have the follwoing spring boot configuration for swagger, when service starts up i get the following error, im not sure exactly why this would be the case. I have followed a tutorial and it works for them.
java.lang.IllegalStateException: Multiple Dockets with the same group name are not supported. The following duplicate groups were discovered. default
#Configuration
#EnableSwagger2
#Import(BeanValidatorPluginsConfiguration.class)
public class SpringFoxConfig {
#Bean
public Docket apiDocket() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("test.rest"))
.paths(PathSelectors.ant("/test/**"))
.build()
.apiInfo(apiInfo());
}
// Describe the apis
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("test")
.description("Test")
.version("1.0.0")
.license("vvv")
.build();
}
}
i also have another config
#OurApp
#EnableSwagger2
public class CoreApp extends OurApp {
}
Here you are trying to do multiple Dockets with the same group name, which is not acceptable. Please review the link provided.
groupName(java.lang.String groupName) If more than one instance of
Docket exists, each one must have a unique groupName as supplied by
this method. Documentation
public class Docket implements DocumentationPlugin {
public static final String DEFAULT_GROUP_NAME = "default";
}
You can see above DocumentPlugin has groupname as "default".
public Docket(DocumentationType documentationType) {
this.apiInfo = ApiInfo.DEFAULT;
this.groupName = "default";
And above has "default" as group name.
So, you need to have two different group names for both the Dockets.
All you need to do is change your code as below: overwrite the existing default groupname.
#Configuration
#EnableSwagger2
#Import(BeanValidatorPluginsConfiguration.class)
public class SpringFoxConfig {
#Bean
public Docket apiDocket() {
String groupName = "Swagger";
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("test.rest"))
.paths(PathSelectors.ant("/test/**"))
.build()
.groupName(groupName)
.apiInfo(apiInfo());
}
// Describe the apis
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("test")
.description("Test")
.version("1.0.0")
.license("vvv")
.build();
}
}
Seems like you have given the same group name which is not accepted, please check and set the group name properly.

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.

Resources