How can I add textbox/textfield in my swagger page built in Spring boot? - 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 { }

Related

How to call Spring Boot RESt api using Spring MVC?

I have created REST api using Spring Boot.
So, that is the fragment of it:
#RestController
#RequestMapping("/api/employee")
public class EmployeeController {
#Autowired
private EmployeeService employeeService;
#GetMapping(value = "/all", produces = "application/json")
public ResponseEntity<List<Employee>> getAllEmployees() {
return ResponseEntity.ok(employeeService.findall());
}
Now, I would like to create more like MVC application part - simple view that shows all Employees using thymeleaf. (Just simple UI to use this app more convinient than sending curl requests)
#Controller
public class MainPageController {
#GetMapping("/employees")
public String showEmployees() {
// i don't know what to do here
return "employeesPage";
}
What is the appropriate way to do so? Is there a more simple way to do it?
Looking forward for your answers!
So you do exactly the same you did on your EmployeeController but instead of a JSON, you return a view.
Get your employes through EmployeeService and put them on a collection
Create your employee view under /templates folder (many tutorials of how to do it)
return this view with your collection of employees
Example:
#GetMapping(value = "employees")
public ModelAndView showEmployees() {
ModelAndView mav = new ModelAndView("employeesPage");
mav.addObject("employees", employeeService.findall());
return mav;
}
Check here for more detailed info:
https://www.thymeleaf.org/doc/articles/springmvcaccessdata.html

AutoConfigure RestController Spring Boot

I have tried to find documentation on how to manually configure a RestController (i.e in a Configuation class). That means without using the RestController annotation. Considering all the other annotations, like mapping, pathvariables etc. is at all possible?
A controller is essentially a component with a request mapping. See RequestMappingHandlerMapping.
#Override
protected boolean isHandler(Class<?> beanType) {
return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
}
If you want to instantiate a "rest controller" through configuration, you can probably do so via the following:
#Configuration
public class MyConfiguration {
#Bean
public MyController() {
return new MyController();
}
}
#ResponseBody
public class MyController {
#RequestMapping("/test")
public String someEndpoint() {
return "some payload";
}
}
But I don't think you'll be able to configure the request mappings (path variables, etc) in the configuration though; at least I haven't seen an example nor figured out how.

Spring Boot swagger file without UI

I have a simple service built in Spring Boot that has a simple API. I've added the springfox libraries to use swagger and the swagger UI, but I do not want my application to serve the UI also. I just want to get the definition from from /api/v1/api-docs
How do I switch off the UI part? Not adding swagger-ui library as a dependency doesn't remove the UI for some reason.
You can block the UI and return HTTP code 404. Something similar to below
#Controller //note - this is a spring-boot controller, not #RestController
public class HomeController {
#RequestMapping ("/swagger/api/v1/api-docs")
public String home(HttpServletRequest request) {
throw new ResourceNotFoundException(); //Custom Solution
or
throw new NoSuchRequestHandlingMethodException(request);
}
}
#ResponseStatus(value = HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException {
...
}
If you are using Spring Boot
#SpringBootApplication
public class MyApp {
public static void main(String[] args) {
SpringApplication.run(MyApp.class, args);
}
#Bean
RouterFunction<ServerResponse> routerFunction() {
return route(GET("/swagger"), req ->
ServerResponse.temporaryRedirect("<some 404 page>").build());
}
}

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 {}]

Hide return value from a Spring MVC controller in SpringFox 2

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());
}

Resources