Hide return value from a Spring MVC controller in SpringFox 2 - spring

I have an async Spring MVC controller that returns Future. SpringFox 2 renders it as this:
How do I remove it? Thank you in advance!

I resolved the issue by adding the following method call to SprinfFox's Docket:
.genericModelSubstitutes(ResponseEntity.class, CompletableFuture.class)
Hope it will help someone.

It does not work with types.
So, let's suppose that this is the controller method:
public CompletableFuture<ResponseEntity<ResponseDTO>> getDTO() {
return CompletableFuture.completedFuture(ResponseEntity.ok(new ResponseDTO());
}
Adding just the configuration:
.genericModelSubstitutes(ResponseEntity.class, CompletableFuture.class)
.directModelSubstitute(CompletableFuture.class, java.lang.Void.class)
it will not work. The method needs to be modified to:
public CompletableFuture getDTO() {
return CompletableFuture.completedFuture(ResponseEntity.ok(new ResponseDTO());
}
Then the CompletableFuture definition will disappear from OpenAPI specs.
Found a better approach. I'm using springfox version 2.8.0. If you have a look at their docs (RTFM) you can have type classes resolved to POJO using a type adapter. An example for this configuration is like this:
import com.fasterxml.classmate.TypeResolver;
#Configuration
#EnableSwagger2
public class SpringFoxConfig {
#Autowired
private TypeResolver typeResolver;
#Bean
public Docket apiDocket() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("base package"))
.paths(PathSelectors.any())
.build()
.genericModelSubstitutes(ResponseEntity.class)
.alternateTypeRules(
newRule(typeResolver.resolve(CompletableFuture.class,
typeResolver.resolve(ResponseEntity.class, WildcardType.class)),
typeResolver.resolve(WildcardType.class)))
.useDefaultResponseMessages(false)
.pathMapping("/");
}
And the controller method can be defined with types:
public CompletableFuture<ResponseEntity<ResponseDTO>> getDTO() {
return CompletableFuture.completedFuture(ResponseEntity.ok(new ResponseDTO());
}

Related

Swagger Models for Throwable and StackTraceElement

Swagger UI shows Models for StackTraceElement and Throwable objects.
I would like to configure it so that these models are not shown.
I have tried annotating the custom class for exceptions with #JsonIgnore:
/** Custom exception class to handle business validation exceptions. */
#JsonIgnoreProperties({"detailMessage", "cause", "stackTrace", "suppressed"})
public class PatientBundleException extends Exception {
#JsonIgnore
public PatientBundleException(String exceptionMessage) {
super(exceptionMessage);
}
}
Here is my Docket:
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("..."))
.paths(PathSelectors.any())
.build()
.apiInfo(apiInfo());
I am using springfox version 2.9.2
If anyone can help assist with configuring Swagger UI to not show models for Throwable and StackTraceElement, that would be much appreciated!
I fixed the issue, it turns out I was extending "Exception" on my model, when I didn't need to.

How set SpringFox to show two (or more) versions of the Rest API using Spring Boot?

I'm trying to figure out how manage two (or more) version of my API endpoints using Spring Fox.
To version my APIs, I'm using the Versioning through content negotiation, also know as Versioning using Accept header. The versions of each endpoint are controlled individually using the header information. Per example, for the version one I use the attribute produces:
#Override
#PostMapping(
produces = "application/vnd.company.v1+json")
public ResponseEntity<User> createUser(
For version two, I use:
#Override
#PostMapping(
produces = "application/vnd.company.v2+json",
consumes = "application/vnd.company.v2+json")
public ResponseEntity<User> createUserVersion2(
I not use consumes for the first (v1) version, so if the client use only application/json on the call the first version will be called by default.
I would like to show the two version on the Swagger UI. How to do that?
It's very simple. Just create one Docket for each version.
Example, the first version:
#Bean
public Docket customImplementation(
#Value("${springfox.documentation.info.title}") String title,
#Value("${springfox.documentation.info.description}") String description) {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo(title, description, "1.0"))
.groupName("v1")
.useDefaultResponseMessages(false)
.securitySchemes(newArrayList(apiKey()))
.pathMapping("/api")
.securityContexts(newArrayList(securityContext())).select()
.apis(e -> Objects.requireNonNull(e).produces().parallelStream()
.anyMatch(p -> "application/vnd.company.v1+json".equals(p.toString())))
.paths(PathSelectors.any())
.build();
}
And for version two:
#Bean
public Docket customImplementationV2(
#Value("${springfox.documentation.info.title}") String title,
#Value("${springfox.documentation.info.description}") String description) {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo(title, description, "2.0"))
.groupName("v2")
.select()
.apis(e -> Objects.requireNonNull(e).produces()
.parallelStream()
.anyMatch(p -> "application/vnd.company.v2+json".equals(p.toString())))
.build();
}
The secret here is filter the available endpoints by the produces attribute.
The Swagger-UI will show the two versions on the combo:
This code needs to be on a class annotated with #Configuration. You also need to enable the Swagger with #EnableSwagger2.
As mentioned by Dherik you can create Docket for each version. But to filter here I have tried using Predicate and custom controller annotations.
Configuration class annotated with #Configuration and #EnableSwagger2
import com.google.common.base.Predicate;
#Bean
public Docket apiV30() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("v30")
.select()
.apis(selectorV30())
.paths(PathSelectors.any()).build().apiInfo(apiEndPointsInfo());
}
private Predicate<RequestHandler> selectorV30(){
return new Predicate<RequestHandler>() {
#Override
public boolean apply(RequestHandler input) {
return input.findControllerAnnotation(SwaggerDocV30.class).isPresent();
}
};
}
#Bean
public Docket apiV31() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("v31")
.select()
.apis(selectorV31())
.paths(PathSelectors.any()).build().apiInfo(apiEndPointsInfo());
}
private Predicate<RequestHandler> selectorV31(){
return new Predicate<RequestHandler>() {
#Override
public boolean apply(RequestHandler input) {
return input.findControllerAnnotation(SwaggerDocV31.class).isPresent();
}
};
}
Custom Annotation class : SwaggerDocV30
#Target({ElementType.TYPE})
#Retention(RetentionPolicy.RUNTIME)
public #interface SwaggerDocV30 {
}
Custom Annotation class : SwaggerDocV31
#Target({ElementType.TYPE})
#Retention(RetentionPolicy.RUNTIME)
public #interface SwaggerDocV31 {
}
Finally annotate your controllers with #SwaggerDocV30 or #SwaggerDocV31
#SwaggerDocV30
#Controller
public class MyController extends AbstractController {}
Or
#SwaggerDocV31
#Controller
public class MyController extends AbstractController {}]

How can I add textbox/textfield in my swagger page built in Spring boot?

I am trying to auto-generate the swagger page for a RestAPI in Spring Boot using annotations.
Code of Controller:
#RestController
#Api(value="UserManagementAPI", produces = MediaType.APPLICATION_JSON_VALUE)
public class UserManagementController {
#RequestMapping("/")
public String index() {
return "Greetings from Spring Boot!";
}
#ApiOperation(value="add a pro",consumes="application/json")
#RequestMapping(value = "/getUser", method = RequestMethod.GET, produces="application/json")
public static List<UserDetails> getUser(#PathVariable(name="id") String id) throws UserException
{
return UserHelper.getUserByEmail(id);
}
Application.java
#SpringBootApplication
#EnableSwagger2
#Configuration
#ComponentScan({ "userManagement"})
#EnableAutoConfiguration
public class Application {
#Bean
public Docket simpleDiffServiceApi() {
return new Docket(DocumentationType.SWAGGER_2).groupName("userManagement").apiInfo(apiInfo()).select()
.apis(RequestHandlerSelectors.any())
// .paths(PathSelectors.any())
// Will also include the basic error controllers by default
.paths(Predicates.not(PathSelectors.regex("/error")))
// Exclude basic error controllers
.build().pathMapping("/");
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder().title("Business Location Service")
.description("Spring Boot REST APIs for Business Location Service")
.contact(new Contact("EntSol-IoT (Niche Technology Delivery Group)", "http://somewebsite.com",
"some#mail.com"))
.version("1.0").build();
}
In the swagger page, I can see all my APIs. But there are more. It is showing all possible method type (e.g POST, GET, PUT etc.) though in Controller I only wrote GET method.
Another issue is that there is no Textbox in the swagger page under the API where I can search for the id. May be I am missing something. I have been trying to resolve it for past two days. But couldn't help myself. Thanks in advance.
I got the problem. Your getUser method is declared as static. Please remove static, for it to work.
public List<UserDetails> getUser(#PathVariable(name="id") String id) throws UserException { }

Is it possible to implement AlternateTypeRules functionallity with annotation?

I've got following issue - https://github.com/springfox/springfox/issues/2373 and I fixed it with the following code:
#Bean
public Docket docket() {
return new Docket(DocumentationType.SWAGGER_2)
.alternateTypeRules(AlternateTypeRules.newRule(TestCarResource.Car.Id.class, String.class));
}
Can I mark my Car.Id class with any annotation to remove this boilerplate code?

Is there a way I can stop springfox swagger from scanning the model classes?

I'm currently using Springfox Swagger to document my spring boot application with a Java config. My API starts in about 75 seconds, (it was originally 20 secs without Springfox) with the whole scanning process. I currently just need the controller information without any model info. Is there a way I can exclude model scanning from the startup process in order to make my API start faster? And are there any other ways to make it faster? I'm using swagger 1.2
There is a way to prevent Sprinfox framework from generating a Swagger model or parameter information of specified ignored types. You have to use the method ignoredParameterTypes in SwaggerSpringMvcPlugin or Docket class to let it know the types to be ignored.
Swagger 1 Example
Here is an example of Swagger 1 Java configuration with ignored types. It definitely had an impact on my application startup time.
#Configuration
#EnableSwagger
public class SwaggerConfiguration {
#Autowired
private SpringSwaggerConfig springSwaggerConfig;
#Bean
public SwaggerSpringMvcPlugin api() {
Class[] clazz = {MyClassA.class, MyClassB.class};
return new SwaggerSpringMvcPlugin(this.springSwaggerConfig)
.apiInfo(apiInfo())
...
.ignoredParameterTypes(clazz);
}
private ApiInfo apiInfo() {
...
}
}
Swagger 2 Example
Here is an example of Swagger 2 Java configuration with ignored types,
#Configuration
#EnableSwagger2
public class SwaggerConfiguration {
#Bean
public Docket api() {
Class[] clazz = {MyClassA.class, MyClassB.class};
return new Docket(DocumentationType.SWAGGER_2)
.groupName("my-group")
.select()
.paths(PathSelectors.any())
.build()
.apiInfo(apiInfo())
.ignoredParameterTypes(clazz);
}
private ApiInfo apiInfo() {
...
}
}
With swagger 3.0 #Hidden annotation is available which is present at package io.swagger.v3.oas.annotations
It can be used on top of the class or method to exclude the resource in swagger documentation.
Springfox Swagger2 acquire UI data through GET /v2/api-docs, which will mapping to springfox.documentation.swagger2.web.Swagger2Controller.getDocumentation().So you can just create a bean to take place of 'ServiceModelToSwagger2Mapper' with your sanning logic:
#Primary
#Component
class CustomServiceModelToSwagger2Mapper : ServiceModelToSwagger2MapperImpl() {
override fun mapDocumentation(from: Documentation?): Swagger? {
// scanning logics...
}
}
refer to my another related answer : https://stackoverflow.com/a/64057512/14332259

Resources