How to enable request duration time in Swagger UI using Springdoc? - spring-boot

I am using the following dependencies for Swagger:
implementation group: 'io.swagger.core.v3', name: 'swagger-annotations', version: '2.2.7'
implementation group: 'org.springdoc', name: 'springdoc-openapi-ui', version: '1.6.12'
My Swagger configuration code is as follows:
#Configuration
public class SwaggerConfig {
#Bean
public GroupedOpenApi publicApi() {
return GroupedOpenApi.builder()
.group("All Apis")
.pathsToMatch("/api/v0/**")
.build();
}
#Bean
public OpenAPI springShopOpenAPI() {
return new OpenAPI()
.info(new Info()
.title("Kaim Tutorial API")
.description("Kaim Tutorial All Apis.")
.version("v0.0.1")
.license(new License().name("Apache 2.0").url("http://springdoc.org")))
.externalDocs(new ExternalDocumentation()
.description("SpringShop Wiki Documentation")
.url("https://springshop.wiki.github.org/docs"));
}
}
What change do I need to make to show every API request duration time in Swagger UI?
I have checked other documentations but they are either for Swagger 2.0 or something that does not use OpenAPI.

Related

How do I hide endpoints only for a specific profile in spring boot?

I am using open api 3 and want to hide some endpoints in swagger ui. In swagger2 I found what can be done in this way by creating my own annotation, but I don't understand how I can do it in openapi3.
#Bean
public Docket postsApi() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("public-api")
.apiInfo(apiInfo())
.select()
// This is the part that will ignore the method
.apis((handler) -> !handler.isAnnotatedWith(IgnoreForProd.class))
.build();
}
I've solved this issue like this:
1st - I have removed the springfox and springfox-swagger-ui dependencies from pom.xml and replaced it with springdoc-openapi-ui like this:
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.6.6</version>
2nd - created the Bean below:
#Configuration
public class OpenAPIConfig {
#Value("${version:unknown}")
private String version;
#Bean
public OpenAPI springShopOpenAPI() {
return new OpenAPI()
.info(new Info().title("Title API")
.description("Description API")
.version(version)
.license(new License().name("Apache 2.0").url("http://springdoc.org")))
.externalDocs(new ExternalDocumentation()
.description("SpringShop Wiki Documentation")
.url("https://springshop.wiki.github.org/docs"));
}
}
3rd - then on application.yml you can filter by package and/or path:
springdoc:
packages-to-scan: com.company.projectxyz.controller
pathsToMatch: /api/whatever/public/**
4th - and if you need to filter different paths/packages per profile, also on application.yml you can do the 3rd step inside of:
spring.config.activate.on-profile: dev/qa/prod...
and access your swagger at /swagger-ui/index.html
I hope it helps =)

swagger-ui doesn't list any of the controllers endpoints

I'm trying to add Swagger to a very simple hello word Spring-Boot project.
I'm following this tutorial :
https://www.baeldung.com/swagger-2-documentation-for-spring-rest-api
this is my SwaggerConfig:
#Configuration
#EnableSwagger2
public class SwaggerConfig{
#Bean
public Docket greetingApi() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("com.example.swaggerready"))
.build()
.apiInfo(metaData());
}
private ApiInfo metaData() {
return new ApiInfoBuilder()
.title("Spring Boot REST API")
.description("\"Spring Boot REST API for greeting people\"")
.version("1.0.0")
.license("Apache License Version 2.0")
.licenseUrl("https://www.apache.org/licenses/LICENSE-2.0\"")
.build();
}
}
However, the results I have running it is only the first page without any information.
This is the repository if someone wants to see the full code.
https://github.com/ThadeuFerreira/SpringMicro
In class SwaggerConfig you need to change line:
.apis(RequestHandlerSelectors.basePackage("com.example.swaggerready"))
To:
.apis(RequestHandlerSelectors.basePackage("com.example.SpringMicro"))

Spring Boot + Swagger-Ui yml generate

Create a swagger-ui with the yaml file generated by swagger-editor
Creating an auto swagger-ui using Annotation was successful.
But I do not know how to create Swagger-ui with yaml created with swagger-editor. Is there anyone who can explain in detail? The development environment uses SpringBoot 2.0.4.
#Configuration
#EnableSwagger2
public class SwaggerConfig {
#Bean
public Docket getApi() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(paths())
.build();
}
private Predicate<String> paths() {
return Predicates.and(
PathSelectors.regex("/shop.*"),
Predicates.not(PathSelectors.regex("/error.*")));
}
}
The above code can make all the APIs inside the server Swagger-ui.
However, I would like to configure swagger-ui with the yaml file that I wrote myself through the swagger-editor.

How to expose Hystrix Stream on Spring Actuator port?

I am using Jetty embedded server in the Spring Boot application.
To handle requests I provide my custom handler like that.
#Slf4j
#Configuration
#EnableWebMvc
#SpringBootApplication
public class Main {
public static void main(String... args) {
new SpringApplicationBuilder().sources(Main.class).run(args);
}
#Bean
public EmbeddedServletContainerCustomizer customizer(JettyRequestHandler myCustomHandler) throws MalformedURLException {
return new EmbeddedServletContainerCustomizer() {
#Override
public void customize(ConfigurableEmbeddedServletContainer container) {
if (container instanceof JettyEmbeddedServletContainerFactory) {
customizeJetty((JettyEmbeddedServletContainerFactory) container);
}
}
private void customizeJetty(JettyEmbeddedServletContainerFactory jetty) {
jetty.addServerCustomizers((JettyServerCustomizer) server -> {
HandlerCollection handlerCollection = new HandlerCollection();
handlerCollection.setHandlers(new Handler[]{myCustomHandler, server.getHandler()});
server.setHandler(handlerCollection);
});
}
};
}
}
I am listening for a requests on a standard 8080 port. I included also Spring Boot Actuator into my project to get some production endpoints (health, etc.). It starts on another port: 8181.
Additionally I am using Hystrix for circuit breaking purposes.
My question is how to enable Hystrix Stream to be exposed on actuator port?
Currently I managed only to expose it on standard port 8080 with following piece of code:
#Bean
public ServletRegistrationBean hystrixStreamServlet(){
return new ServletRegistrationBean(new HystrixMetricsStreamServlet(), "/hystrix.stream");
}
But I would like to expose it on another, to have the default one only for application purposes.
Those are some of my dependecies:
compile 'com.netflix.hystrix:hystrix-core:1.5.3'
compile 'com.netflix.hystrix:hystrix-metrics-event-stream:1.5.3'
compile 'org.springframework.boot:spring-boot-starter-actuator:1.3.5.RELEASE'
I would like NOT to use Spring Cloud where is #EnableHystrix that gives the stream on the actuator port actually.
Actually I did what #m-deinum proposed and it worked. I used Spring Cloud Stack.
To achieve Hystrix Stream on actuator I added dependecies:
compile group: 'org.springframework.cloud', name: 'spring-cloud-starter', version: '1.1.1.RELEASE' // spring cloud starter
compile group: 'org.springframework.cloud', name: 'spring-cloud-starter-hystrix', version: '1.1.3.RELEASE' // spring cloud hystrix starter
compile group: 'org.springframework.cloud', name: 'spring-cloud-starter-ribbon', version: '1.1.3.RELEASE' // spring ribbon starter
And the annotation on the Main class:
#EnableCircuitBreaker
#SpringBootApplication
public class Main {
public static void main(String... args) {
new SpringApplicationBuilder().sources(Main.class).run(args);
}
// ...
}

Springfox swagger - no api-docs with spring boot jersey and gradle

I have a spring boot application with jersey and gradle, and I am trying to automatically generate the API documentation using springfox.
I have followed the steps here: http://springfox.github.io/springfox/docs/current/
Here is what I did:
build.gradle:
dependencies {
.........
//Swagger
compile "io.springfox:springfox-swagger2:2.4.0"
compile "io.springfox:springfox-bean-validators:2.4.0"
compile 'io.springfox:springfox-swagger-ui:2.4.0'
}
Spring boot Application:
#SpringBootApplication
#EnableSwagger2
public class AnalyzerServiceApplication{
public static void main(String[] args) {
SpringApplication.run(AnalyzerServiceApplication.class, args);
}
#Bean
public Docket analyzerApi() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build()
.pathMapping("/")
.directModelSubstitute(LocalDate.class, String.class)
.genericModelSubstitutes(ResponseEntity.class)
.alternateTypeRules(
newRule(typeResolver.resolve(DeferredResult.class,
typeResolver.resolve(ResponseEntity.class, WildcardType.class)),
typeResolver.resolve(WildcardType.class)))
.useDefaultResponseMessages(false)
.globalResponseMessage(RequestMethod.GET,
newArrayList(new ResponseMessageBuilder()
.code(500)
.message("500 message")
.responseModel(new ModelRef("Error"))
.build()))
.securitySchemes(newArrayList(apiKey()))
.securityContexts(newArrayList(securityContext()))
.enableUrlTemplating(true)
.globalOperationParameters(
newArrayList(new ParameterBuilder()
.name("someGlobalParameter")
.description("Description of someGlobalParameter")
.modelRef(new ModelRef("string"))
.parameterType("query")
.required(true)
.build()))
.tags(new Tag("Pet Service", "All apis relating to pets"))
;
}
#Autowired
private TypeResolver typeResolver;
private ApiKey apiKey() {
return new ApiKey("mykey", "api_key", "header");
}
private SecurityContext securityContext() {
return SecurityContext.builder()
.securityReferences(defaultAuth())
.forPaths(PathSelectors.regex("/anyPath.*"))
.build();
}
List<SecurityReference> defaultAuth() {
AuthorizationScope authorizationScope
= new AuthorizationScope("global", "accessEverything");
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
authorizationScopes[0] = authorizationScope;
return newArrayList(
new SecurityReference("mykey", authorizationScopes));
}
#Bean
SecurityConfiguration security() {
return new SecurityConfiguration(
"test-app-client-id",
"test-app-client-secret",
"test-app-realm",
"test-app",
"apiKey",
ApiKeyVehicle.HEADER,
"api_key",
"," /*scope separator*/);
}
#Bean
UiConfiguration uiConfig() {
return new UiConfiguration("validatorUrl");
}
Now the controller (Jersey)
#Api(value = "/widget")
#Path("/widget")
#Component
public class WidgetController extends BaseController {
#Autowired
private WidgetService widgetService;
#GET
#Path("/secHealth")
#ApiOperation(value = "Find pet by ID", notes = "Returns a pet when ID < 10. ID > 10 or nonintegers will simulate API error conditions", response = Pet.class)
#ApiResponses(value = { #ApiResponse(code = 400, message = "Invalid ID supplied"),
#ApiResponse(code = 404, message = "Pet not found") })
public Response getPet() {
//Do something
}
When I start the server and navigate to http://localhost:8080/swagger-ui.html, I can see the "green" UI screen with only the basic-error-controller listed there. My own controller is not there.
What did I do wrong?
Thanks
Guy
As of version 2.5.0 springfox only supports spring-mvc controllers. Jax-rs implementations like jersey aren't supported.
The current alternative to using springfox is to use the swagger-core library for jax-rs/jersey based services.
It does have the hooks needed to implement support for jersey in 2.6+. Here is an excerpt of a way to implement it in this issue
Currently ResourceConfig has a method called "getClasses" which will
list everything registerted. like Resources, Filters,etc... Maybe this
could help. But be aware that the returning classes could also be
filters or any other stuff you could register with jersey2.
To be able to see Jersey methods from Springfox swagger UI:
Configure your Swagger with Jersey following https://github.com/swagger-api/swagger-core/wiki/Swagger-Core-Jersey-2.X-Project-Setup-1.5
Configure Springfox Swagger following http://springfox.github.io/springfox/docs/current/
Add in you SpringBoot application configuration class (annotated with #Configuration):
#Value("${springfox.documentation.swagger.v2.path}")
private String swagger2Endpoint;
In application.properties add reference to your Jersey swagger.json:
springfox.documentation.swagger.v2.path=/{change it to your Jersey api path}/swagger.json
Now you should be able to see Jersey Swagger generated api from Springfox Swagger UI page.
Thanks #Dilip-Krishnan for the springfox update and #Guy-Hudara for the question, I came up with the following solution to get swagger support in my springboot jersey powered app :
import io.swagger.jaxrs.config.BeanConfig;
import io.swagger.jaxrs.listing.ApiListingResource;
import io.swagger.jaxrs.listing.SwaggerSerializers;
import org.glassfish.jersey.server.ResourceConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
/**
* As of version 2.5.0 springfox only supports spring-mvc controllers. Jax-rs implementations like jersey aren't supported.
*
* Fortunately io.swagger::swagger-jersey2-jaxrs::1.5.3 have the hooks needed to implement support for jersey in 2.6+.
*
* some pointers I used to get this swagger config done and swagger-core, springboot and jersey integrated:
* http://stackoverflow.com/questions/37640863/springfox-swagger-no-api-docs-with-spring-boot-jersey-and-gardle
* https://www.insaneprogramming.be/blog/2015/09/04/spring-jaxrs/
* https://github.com/swagger-api/swagger-core/wiki/Swagger-Core-Jersey-2.X-Project-Setup-1.5#adding-the-dependencies-to-your-application
*
*/
#Configuration
public class SwaggerConfiguration {
#Autowired
ResourceConfig resourceConfig;
#PostConstruct
public void configure() {
resourceConfig.register(ApiListingResource.class);
resourceConfig.register(SwaggerSerializers.class);
BeanConfig beanConfig = new BeanConfig();
beanConfig.setVersion("1.0.2");
beanConfig.setSchemes(new String[]{"http"});
beanConfig.setHost("localhost:8888");
beanConfig.setBasePath("/api");
beanConfig.setResourcePackage("com.my.resource");
beanConfig.setPrettyPrint(true);
beanConfig.setScan(true);
}
}
That worked out great for me

Resources