Hide a method in SpringFox swagger-ui - spring-boot

I'm using SpringFox 3.0.0 in a SpringBoot (2.6.2) project.
My SpringBoxConfig.class file is:
/** SpringFoxConfig. */
#Configuration
#EnableSwagger2
#ComponentScan(basePackageClasses = {
CcController.class,
AreaController.class,
SubAreaController.class,
ProcController.class
})
public class SpringFoxConfig {
public static final String AREAS = "Areas";
public static final String AREAS_DESC =
"Provides access to Areas endpoints in ms-filters.";
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors
.basePackage(
"com.munidigital.bookingform.bffweb.application.web.incoming"))
.paths(PathSelectors.any())
.build()
.tags(new Tag(AREAS, AREAS_DESC))
.apiInfo(getApiInfo());
}
...
My AreaController.java is:
/** AreaController. */
#Api(tags = SpringFoxConfig.AREAS)
#RestController
public class AreaController {
#GetMapping(value = {"/v1/areas/", "/v1/areas/{id}"})
public ResponseEntity<?> read(
#PathVariable(required = false) Optional<Long> id) {
LOG.info("AreaController: read");
...
return response;
}
...
The output is:
My problem:
I need to hide the operation (/bookingform/api/web/v1/areas/) and just show /bookingform/api/web/v1/areas/{id}.
I want to see something like this:
I've tried #ApiIgnore, #Hidden, and #ApiOperation(hidden=true) but no results were achieved since I don't know how to indicate which is the URI that I want to hide. Both are shown or hidden. I couldn't get it to show only one.

Related

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.

Swagger doesn't display information about methods - SpringBoot

I have an API in Java SpringBoot and I want to document it in Swagger.
I have done the following (I only include classes that contain some code related to Swagger):
Main class
#EnableSwagger2
public class ProvisioningApiApplication {
public static void main(String[] args) {
if (AuthConfigFactory.getFactory() == null) {
AuthConfigFactory.setFactory(new AuthConfigFactoryImpl());
}
SpringApplication.run(ProvisioningApiApplication.class, args);
}
#Bean
public Docket swaggerSpringMvcPluggin() {
return new Docket(DocumentationType.SWAGGER_2)
.useDefaultResponseMessages(false)
.apiInfo(apiInfo())
.select()
.paths(Predicates.not(PathSelectors.regex("/error.*")))
.build();
}
#Component
#Primary
public class CustomObjectMapper extends ObjectMapper {
public CustomObjectMapper() {
setSerializationInclusion(JsonInclude.Include.NON_NULL);
configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
enable(SerializationFeature.INDENT_OUTPUT);
}
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Provisioning API")
.version("0.0.1")
.build();
}
}
Controller
#RestController
#EnableAutoConfiguration
#CrossOrigin
public class RecursoController {
#Autowired
private Configuration configuration;
#Autowired
private TypeSpecService typeSpecService;
#Autowired
private IoTAgentService ioTAgentService;
#Autowired
private OrionService orionService;
#Autowired
private DeviceIdService deviceIdService;
#ApiOperation(value = "Put a device", nickname = "provisionDevice", tags = "Device")
#ApiResponses({
#ApiResponse(code = 200, message = "Ok", response = NewDeviceResponse.class)
})
#RequestMapping(method = RequestMethod.PUT, value = "/devices", consumes = "application/json", produces = "application/json")
public ResponseEntity<NewDeviceResponse> provisionDevice(#RequestBody NewDeviceRequest newDeviceRequest,
#RequestHeader("X-Auth-Token") String oAuthToken) {
// what my method does
}
The documentation results in the following swagger.json file:
{
swagger: "2.0",
info: {
version: "0.0.1",
title: "Provisioning API"
},
host: "localhost:8080",
basePath: "/"
}
As you can see, it only contains the name and the version of API but not the provisionDevice method.
I've tried everything but I can't figure it out what I'm doing bad. What am I missing?
Did you add #Api annotation in your class, where you have your main services?

How to consume protobuf parameters using Spring REST?

I'm trying to pass a protobuf parameter to a REST endpoint but I get
org.springframework.web.client.HttpServerErrorException: 500 null
each time I try. What I have now is something like this:
#RestController
public class TestTaskEndpoint {
#PostMapping(value = "/testTask", consumes = "application/x-protobuf", produces = "application/x-protobuf")
TestTaskComplete processTestTask(TestTask testTask) {
// TestTask is a generated protobuf class
return generateResult(testTask);
}
}
#Configuration
public class AppConfiguration {
#Bean
ProtobufHttpMessageConverter protobufHttpMessageConverter() {
return new ProtobufHttpMessageConverter();
}
}
#SpringBootApplication
public class JavaConnectorApplication {
public static void main(String[] args) {
SpringApplication.run(JavaConnectorApplication.class, args);
}
}
and my test looks like this:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest
#WebAppConfiguration
public class JavaConnectorApplicationTest {
#Configuration
public static class RestClientConfiguration {
#Bean
RestTemplate restTemplate(ProtobufHttpMessageConverter hmc) {
return new RestTemplate(Arrays.asList(hmc));
}
#Bean
ProtobufHttpMessageConverter protobufHttpMessageConverter() {
return new ProtobufHttpMessageConverter();
}
}
#Autowired
private RestTemplate restTemplate;
private int port = 8081;
#Test
public void contextLoaded() {
TestTask testTask = generateTestTask();
final String url = "http://127.0.0.1:" + port + "/testTask/";
ResponseEntity<TestTaskComplete> customer = restTemplate.postForEntity(url, testTask, TestTaskComplete.class);
// ...
}
}
I'm sure that it is something with the parameters because if I create a variant which does not take a protobuf parameter but returns one it just works fine. I tried debugging the controller code but the execution does not reach the method so the problem is probably somewhere else. How do I correctly parametrize this REST method?
This is my first stack overflow answer but I was a lot to frustred from searching for working examples with protobuf over http and spring.
the answer https://stackoverflow.com/a/44592469/15705964 from Jorge is nearly correct.
Like the comments mention: "This won't work in itself. You need to add a converter somewhere at least."
Do it like this:
#Configuration
public class WebConfig implements WebMvcConfigurer {
#Autowired
ProtobufHttpMessageConverter protobufHttpMessageConverter;
#Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(protobufHttpMessageConverter);
}
}
The ProtobufHttpMessageConverter will do his job automatically and add the object to your controller methode
#RestController
public class ProtobufController {
#PostMapping(consumes = "application/x-protobuf", produces = "application/x-protobuf")
public ResponseEntity<TestMessage.Response> handlePost(#RequestBody TestMessage.Request protobuf) {
TestMessage.Response response = TestMessage.Response.newBuilder().setQuery("This is a protobuf server Response")
.build();
return ResponseEntity.ok(response);
}
Working example with send and reseive with rest take a look: https://github.com/Chriz42/spring-boot_protobuf_example
Here it's the complete answer
#SpringBootApplication
public class JavaConnectorApplication {
public static void main(String[] args) {
SpringApplication.run(JavaConnectorApplication.class, args);
}
}
Then you need to provide the right configuration.
#Configuration
public class AppConfiguration {
//You need to add in this list all the messageConverters you will use
#Bean
RestTemplate restTemplate(ProtobufHttpMessageConverter hmc) {
return new RestTemplate(Arrays.asList(hmc,smc));
}
#Bean
ProtobufHttpMessageConverter protobufHttpMessageConverter() {
return new ProtobufHttpMessageConverter();
}
}
And finally your RestController.
#RestController
public class TestTaskEndpoint {
#PostMapping(value = "/testTask")
TestTaskComplete processTestTask(#RequestBody TestTask testTask) {
// TestTask is a generated protobuf class
return generateResult(testTask);
}
}
The #RequestBody annotation: The body of the request is passed through an HttpMessageConverter (That you already defined) to resolve the method argument depending on the content type of the request
And your test class:
#RunWith(SpringRunner.class)
#SpringBootTest
#WebAppConfiguration
public class JavaConnectorApplicationTest {
#Autowired
private RestTemplate restTemplate;
private int port = 8081;
#Test
public void contextLoaded() {
TestTask testTask = generateTestTask();
final String url = "http://127.0.0.1:" + port + "/testTask/";
ResponseEntity<TestTaskComplete> customer = restTemplate.postForEntity(url, testTask, TestTaskComplete.class);
// Assert.assertEquals("dummyData", customer.getBody().getDummyData());
}
}

Resources