generating spring API docs using swagger over GET endpoints with complex objects - spring

I have a spring boot app and I am using springfox swagger to generate the API documentation.
I have a search endpoint with a complex, nested object
#GetMapping("/search")
public Something search(SearchDTO input) {
}
public class SearchDTO {
private SearchFilterDto filters;
private Page page;
private Sort sort;
}
public class SearchFilterDto {
private String name;
}
... other DTOS; getters and setters are omitted, default constructor
<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>
After running the app, the generated doc looks like this
Any ideas on to can I help springfox generate documentation for my complex object?

I have found the problem.
In my DTOs I had some getters which return Optional<Something>. By adding .genericModelSubstitutes(Optional.class) to my swagger config I managed to obtain the configuration I was looking for.
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build()
.genericModelSubstitutes(Optional.class) // added this line
.securityContexts(Lists.newArrayList(securityContext()))
.securitySchemes(Lists.newArrayList(apiKey()));
}

Related

SpringBoot - SpringFox Starter 3.0.0 - Unable to detect WebFlux RouterFunction

I am using SpringBoot WebFlux Springfox-starter for the project.
The issue is this not detecting the RouterFunction methods. The above methods are detecting without any issues but it is not working for RouterFunctions.
#Bean
public RouterFunction<ServerResponse> route(GreetingHandler greetingHandler) {
return RouterFunctions
.route(RequestPredicates.GET("/hello")
.and(RequestPredicates.accept(MediaType.TEXT_PLAIN)),
greetingHandler::hello);
}
#Component
public static class GreetingHandler {
public Mono<ServerResponse> hello(ServerRequest request) {
return ServerResponse.ok()
.contentType(MediaType.TEXT_PLAIN)
.body(BodyInserters.fromValue("Hello, SpringFox!"));
}
}
https://github.com/springfox/springfox
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
I have hosted the entire project in the below location. Please let me know if anyone experience the same or additional configuration missing here.
https://github.com/chamithchathuka/demowebflux-2
https://github.com/chamithchathuka/demowebflux-2/tree/master

Swagger 3 with Springboot: Unable to infer base url

I use Springboot with swagger 3:
<!-- SWAGGER -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
I use a default /api prefix to all my endpoints.
This is how I configured my SwaggerConfig:
#Configuration
#EnableSwagger2
public class SwaggerConfig {
public static final String AUTHORIZATION_HEADER = "Authorization";
#Bean
public Docket api() {
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.securityContexts(Collections.singletonList(securityContext()))
.securitySchemes(Collections.singletonList(apiKey()))
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build().pathMapping("/api");
return docket;
}
private ApiKey apiKey() {
return new ApiKey("JWT", AUTHORIZATION_HEADER, "header");
}
// ......
}
When I try to access to my swagger-ui http://myhost/swagger-ui I get a popup with this message Unable to infer base url. This is common when using dynamic servlet registration or when the API is behind an API Gateway. The base url is the root of where all the swagger resources are served. For e.g. if the api is available at http://example.org/api/v2/api-docs then the base url is http://example.org/api/. Please enter the location manually: asking me to define the location with.
When I enter my prefix manually : http://myhost/api then every thing is fine.
Any idea how to define my REST API prefix ?

Configure Spring Boot to use Custom Access Token converter

I'm trying to get user information from the access token provided by an Identity Provider. The Identity Provider that I'm using provides it's scope in the form of a string instead of a list because of which the DefaultAccessTokenConverter doesn't work for me. As a result I wish to extend it to a CustomAccessTokenConverter to override it's extractAuthentication() method. I'm using the following in my security config to make Spring use this custom class instead of the default one:
#Configuration
#EnableResourceServer
public class SecurityConfig extends ResourceServerConfigurerAdapter {
#Autowired
private CustomAccessTokenConverter customAccessTokenConverter;
// For validating the incoming access token and fetching user information from it
#Bean
public ResourceServerTokenServices createResourceServerTokenServices() {
RemoteTokenServices tokenServices = new RemoteTokenServices();
tokenServices.setCheckTokenEndpointUrl(*Introspection URL*);
tokenServices.setClientId(*Client ID*);
tokenServices.setClientSecret(*Client Secret*);
return tokenServices;
}
#Bean
public AccessTokenConverter accessTokenConverter() {
return customAccessTokenConverter;
}
}
But, Spring still uses the DefaultAccessTokenConverter. What am I doing wrong? Please help me out here.
Here is what my CustomAccessTokenConverter class looks like just for reference:
#Component
public class CustomAccessTokenConverter extends DefaultAccessTokenConverter {
#Override
public OAuth2Authentication extractAuthentication(Map<String, ?> map) {
.
.
.
return new OAuth2Authentication(request, user);
}
}
I am using Spring Boot with the following dependencies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.0.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-resource-server</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
ResourceTokenServices allows us to use our own AccessTokenConverter.
Simply add the following to your security config:
#Bean
public ResourceServerTokenServices createResourceServerTokenServices() {
RemoteTokenServices tokenServices = new RemoteTokenServices();
tokenServices.setCheckTokenEndpointUrl(*Introspection URL*);
tokenServices.setClientId(*Client ID*);
tokenServices.setClientSecret(*Client Secret*);
// ADD THE NEXT LINE
tokenServices.setAccessTokenConverter(customAccessTokenConverter);
return tokenServices;
}

Generate YAML format response in springboot

I want to generate YAML format type response using Spring boot. can you please help me here to get it out?
Ensure you have the following dependency on the classpath:
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
<version>${jackson.version}</version>
</dependency>
Then define your own HttpMessageConverter:
class MappingJackson2YamlHttpMessageConverter extends AbstractJackson2HttpMessageConverter {
MappingJackson2YamlHttpMessageConverter(ObjectMapper objectMapper) {
super(objectMapper, MediaType.parseMediaType("application/x-yaml"));
}
}
Expose it as a Spring #Bean:
#Configuration
public class JacksonYamlConfig {
#Bean
public MappingJackson2YamlHttpMessageConverter yamlHttpMessageConverter() {
YAMLMapper mapper = new YAMLMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
return new MappingJackson2YamlHttpMessageConverter(mapper);
}
}
And finally configure your controller method to produce YAML:
#GetMapping(produces = "application/x-yaml")
public ResponseEntity<Foo> getFoo() {
...
}

Spring Integration with swagger: How can I implement it?

Cant expose spring integration flow apis, with swagger documentation
I have some apis exposed using spring integration. We tried document it, with springfox dependency (swagger2).
But when access to: http://localhost:8080/myProject/swagger-ui.html, the page is empty, we cant see the services with swagger format
My example;
Class definition:
#Configuration
#EnableSwagger2
public class ConsultaBdnFlow {
....
}
Swagger configuration:
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build();
}
Swagger Dependencies:
<!-- Start Swagger 2 with SpringFox -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.3.0</version>
</dependency>
<!-- End Swagger 2 with SpringFox -->
Flow to expose the service:
#Bean
public IntegrationFlow bdnBlacklistFlow() {
return IntegrationFlows
.from(Http.inboundGateway("/consultas/bdn")
.requestPayloadType(String.class)
.requestChannel(requestBlacklistChannel())
.replyChannel(replyBlacklistChannel())
)
.get();
}
When run the project we can access to http://localhost:8080/swagger-ui.html, but dont see the service swagger document
Maybe you are missing VendorExtension.
Change your Docket Bean to something like this and see what happens. Also include the errors it is giving you if it doesn't work. This worked on Swagger dependencies (2.9.2) and Spring-boot 2.2.0.M2.
#Bean
public Docket apiDocket() {
Contact contact = new Contact(
"You name",
"Your webesite",
"Your email"
);
List<VendorExtension> vendorExtensions = new ArrayList<>();
ApiInfo apiInfo = new ApiInfo(
"RESTful API documentation",
"This pages documents Turing Ecommerce RESTful API endpoints", "1.0",
"Website", contact,
"Apache 2.0", "http://www.apache.org/licenses/LICENSE-2.0",vendorExtensions);
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo)
.select()
.apis(RequestHandlerSelectors.basePackage("com.company.package"))
.paths(PathSelectors.any())
.build();
return docket;
}

Resources