Swagger doesn't display information about methods - SpringBoot - spring-boot

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?

Related

Spring webflux reactive api always returning 404 error

Here is my main class
#SpringBootApplication
#ComponentScan(basePackages= {"com.test"
})
public class Application {
public static void main(String... args) {
System.setProperty("spring.devtools.restart.enabled", "false");
Properties props = BootProperties.forService(
"test", "test", "test");
new SpringApplicationBuilder(
Application.class)
.properties(props)
.run(args);
}
RestController
#RestController
public class PersonController {
private ARepository aRepo;
PersonController(ARepository aRepo) {
this.aRepo = aRepo;
}
#PostMapping(path = "/books", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public Mono<VO> createBook(#Valid #RequestBody VO vo) {
return apply(vo);
}
public Mono<VO> apply(VO vo) {
Mono<VO> alternate = Mono.fromCallable(() -> {
return aRepo.findById(vo.getId1(), vo.getId2());
}).flatMapMany(Flux::fromIterable).next().map(n -> build(vo, n)).subscribeOn(Schedulers.elastic());
return alternate;
}

Why Swagger not showing all methods in same class?

i'm trying to use swagger with my code , but not all methods are listing in swagger-ui some methods not show
i am using swagger 2.5.0 version ,and spring boot 2.1.0.RELEASE
my user rest controller
#RestController
#RequestMapping(value = "/rest")
public class UserRestController {
#Autowired
private UserService userService;
#RequestMapping(method = RequestMethod.GET, value = "/users")
public Iterator<User> getUsers() {
return userService.getUsers();
}
#RequestMapping(method = RequestMethod.GET, value = "/user/{id}")
public User getUser(#PathVariable("id") Long id) {
return userService.getUser(id);
}
#RequestMapping(method = RequestMethod.POST, value = "/user")
public User save(#RequestBody User user) {
User userValidation = userService.getUser(user.getId());
if (userValidation != null) {
throw new IllegalAddException("username already used !");
}
return userService.save(user);
}
#RequestMapping(method = RequestMethod.DELETE, value = "/user")
public User delete(#RequestBody User user) {
return userService.save(user);
}
}
and this my config code
#Configuration
#EnableSwagger2
public class SwaggerApi {
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2).select()
.apis(RequestHandlerSelectors.basePackage("com.social.core.rest")).paths(PathSelectors.ant("/rest/*"))
.build().apiInfo(apiInfo());
}
private ApiInfo apiInfo() {
return new ApiInfo("Social API", "Soccial api for gamerz zone.", "API TOS", "Terms of service",
new Contact("yali", "www.social.com", "prg#gmail.com"), "License of API",
"API license URL");
}
}
getUser method not showing in swagger ui , and the method worked when i hit url and already getting data
just three method are showing
I solved this issue by adding more star in paths with me config
paths(PathSelectors.ant("/rest/**"))

spring boot swagger ui not showing

this is what I am seeing enter image description here
my SwaggerConfig.java
#Configuration
#EnableSwagger
#ComponentScan("pollingDemo")
public class SwaggerConfig {
private SpringSwaggerConfig springSwaggerConfig;
#Autowired
public void setSpringSwaggerConfig(SpringSwaggerConfig springSwaggerConfig) {
this.springSwaggerConfig = springSwaggerConfig;
}
#Bean
public SwaggerSpringMvcPlugin customImplementation() {
return new SwaggerSpringMvcPlugin(this.springSwaggerConfig).apiInfo(apiInfo())
.useDefaultResponseMessages(false)
.includePatterns("/api/.*");
}
private ApiInfo apiInfo() {
ApiInfo apiInfo = new ApiInfo("Demo APIs", "APIs for Demo",
"http://www.jemrug.com",
"donotuse#donotuse",
"© MIT Copyright", "http://www.opensource.org/licenses/mit-license.php");
return apiInfo;
}
}
My Controller has the following annotations:-
#Api(basePath = "api", value = "/Hello", description = "Operations with person", produces = "application/json")
#RestController
public class GreetingController {
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
#ApiOperation(httpMethod = "GET", value = "Say Hello To World greeting using Swagger",notes ="hello")
#RequestMapping("/greeting")
public Greeting greeting(#RequestParam(value="name", defaultValue="World") String name) {
return new Greeting(counter.incrementAndGet(),
String.format(template, name));
}
}
What am I doing wrong?
Arrrrgh Help someone please
Regards,
Jemrug

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

Jersey 2.13 + Bean Validation

I'm using gradle and the following libs:
ext.library['jersey'] = "org.glassfish.jersey:project:2.13"
ext.library['jersey_jettison'] = "org.glassfish.jersey.media:jersey-media-json-jettison:2.13"
ext.library['jersey_jackson'] = "org.glassfish.jersey.media:jersey-media-json-jackson1:2.13"
ext.library['jersey_spring'] = "org.glassfish.jersey.ext:jersey-spring3:2.13"
ext.library['jersey_bean_validation'] = "org.glassfish.jersey.ext:jersey-bean-validation:2.13"
I created the bean validation structure, but its not validating at all. No error messages, nothing. This is the structure I've created:
The DTO
public class MergeSchedulesDto {
#NotNull(message = "validation.invalid.mergeFrom")
private Long mergeFrom;
#NotNull(message = "validation.invalid.mergeTo")
#NotEmpty(message = "validation.invalid.mergeTo")
private List<Long> mergeTo;
The Service
#Path("merge")
#POST
#Consumes({ MediaType.APPLICATION_JSON })
public Response merge(#Valid MergeSchedulesDto dto, #QueryParam("units") List<Long> units) {
The config
public class ApplicationJAXRS extends Application {
public ApplicationJAXRS() {
}
#Override
public Map<String, Object> getProperties() {
Map<String, Object> properties = new HashMap<>();
properties
.put("jersey.config.server.provider.packages",
"com.sifionsolution.sig.academic.resource.service,com.sifionsolution.sig.integration.resource.filter,com.sifionsolution.sig.academic.param.converter,com.sifionsolution.sig.datatables.resource.service,com.sifionsolution.sig.datatables.converter");
return properties;
}
#Override
public Set<Object> getSingletons() {
Set<Object> singletons = new HashSet<>();
singletons.add(new Jackson1Feature());
singletons.add(new ValidationExceptionMapper());
return singletons;
}
}
EDIT I forgot the provider:
#Provider
public class ValidationExceptionMapper implements ExceptionMapper<ConstraintViolationException> {
#Override
public Response toResponse(ConstraintViolationException exception) {
return Response.status(BAD_REQUEST).entity(exception.getMessage()).build();
}
}
EDIT 2: I removed the JUnit test because I didnt test using Jersey Test Framework.
The problem here is that the ValidationExceptionMapper is not beeing called.
Put "#Valid" in your, like this:
#POST
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public Response insert(#Valid T obj) throws Exception{
...
}
This works here.

Resources