swagger annotation content-type not set - spring

I have this spring rest controller:
#RestController
#RequestMapping("/communications")
class CommunicationController(private val service: CommunicationService) {
#ApiOperation(
produces = APPLICATION_JSON_VALUE,
consumes = APPLICATION_JSON_VALUE
)
#GetMapping(
consumes = [APPLICATION_JSON_VALUE],
produces = [APPLICATION_JSON_VALUE]
)
fun findAll(
criterias: CommunicationCriterias,
page: Pageable
): List<CommunicationDTO> = service.findCommunications(criterias, page)
}
When I test this endpoint via the swagger-ui (springfox) interface, i got a 415: content type invalid error. It seems that content-type: application/json is not set in the header.
What is missing ?

There is nothing to consume in HTTP GET request. I think you should remove the consumes from #GetMapping and #ApiOperation.

Related

No http client metrics for non 200 response codes in Quarkus Micrometer

I have the following Quarkus Rest client code (based on this doc https://quarkus.io/guides/rest-client)
#RegisterRestClient(baseUri = "https://pesho3.free.beeceptor.com")
interface TokenService {
#POST
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
#Produces(MediaType.APPLICATION_JSON)
#ClientHeaderParam(
name = "Authorization",
value = ["Basic asdasd"]
)
fun getToken(
#FormParam("grant_type") grantType: String = "client_credentials",
#FormParam("scope") scope: String = "IIG-HIP-NP/Read"
): JSONObject
}
When I call my getToken() method and get http 200 I get automatically generated metrics in localhost:8080/q/metrics (as stated in this doc https://quarkus.io/guides/micrometer#review-automatically-generated-metrics)
e.g
http_client_requests_seconds_count{clientName="pesho3.free.beeceptor.com",method="POST",outcome="SUCCESS",status="200",uri="root",} 2.0
http_client_requests_seconds_sum{clientName="pesho3.free.beeceptor.com",method="POST",outcome="SUCCESS",status="200",uri="root",} 1.116203
I don't get any metrics for non 200 codes.. How can I expose them ?
I found the solution.. Its this property (not mentioned in Quarkus doc)
microprofile.rest.client.disable.default.mapper=true
The answer was in this doc:
https://download.eclipse.org/microprofile/microprofile-rest-client-1.3/microprofile-rest-client-1.3.html#_default_responseexceptionmapper

How to do java unit test with protobuf for controller?

I have a spring boot rest controller with requestBody & responseBody both protobuf. like below :
#RequestMapping(value = "/position/open", produces = "application/x-protobuf")
#ResponseBody
public MsgProto.Response positionOpen(#RequestBody MsgProto.Request request)throws Exception {
log.info("start /position/open");
return orderPositionService.addOrder(request);
}
Now I want to do a unit test using mockMvc to test the controller, but it failed every time. I believe it is the code below which is wrong to fire an HTTP request with protobuf, any idea how to resolve it?
mockMvc.perform(post("/position/open").contentType("application/x-protobuf")
.content(ObjectsMock.mockMsgProtoRequest().toByteArray())).andDo(print())
.andExpect(status().isOk());
Exception :
Resolved Exception:
Type = org.springframework.web.HttpMediaTypeNotSupportedException
MockHttpServletResponse:
Status = 415
Error message = null
Headers = [Accept:"application/json, application/octet-stream,
application/xml, application/*+json, text/plain, text/xml, application/x-www-
form-urlencoded, application/*+xml, multipart/form-data, multipart/mixed, */*"]
I assume the ProtobufHttpMessageConverter is missing here. Spring MVC can't read/write any messages without this specific converter.
You can create it as the following:
#Bean
public ProtobufHttpMessageConverter protobufHttpMessageConverter() {
return new ProtobufHttpMessageConverter();
}
Next, make sure to add the HTTP Method to your method, as I assume (from reading your test) you want this to be a HTTP POST handler. You can also add the consumes attribute to state that this endpoint also consumes Protobuf.
#RequestMapping(method = RequestMethod.POST, consumes = "application/x-protobuf", value = "/position/open", produces = "application/x-protobuf")
#ResponseBody
public MsgProto.Response positionOpen(#RequestBody MsgProto.Request request)throws Exception {
log.info("start /position/open");
return orderPositionService.addOrder(request);
}
In addition to this, there is an article on the Spring blog available that covers your usecase and explains how to use Protobuf with Spring MVC.
You need to add Protobuf converter to MockMvc builder
MockMvcBuilders.standaloneSetup(controller)
.setMessageConverters(new ProtobufHttpMessageConverter())
.build()
This fixed the issue for me

Unable to upload file due to Content-Type "multipart/form-data" not set for request body of type StandardMultipartFile

I have a remote service A which does the file upload. I have service B which calls the upload API of service A through FeignClient to upload a file
The method definition in Service A is something like
ResponseEntity<?> upload(#RequestPart("file") MultipartFile file) { }
And the method in Service B is
#FeignClient(url = "http://localhost:5000/")
public interface uploadService {
#RequestMapping(method = RequestMethod.POST, value = "/serviceA/upload")
#Headers("Content-Type: multipart/form-data")
void uploadFile(#RequestPart("file") MultipartFile file);
}
I am getting the error
Content-Type "multipart/form-data" not set for request body of type StandardMultipartFile
I have tried most of the suggestions on https://github.com/spring-cloud/spring-cloud-netflix/issues/867 and
https://github.com/OpenFeign/feign-form but nothing works for me
I was able to solve this issue by simply adding consumes = "multipart/form-data" in the RequestMapping. The reason was that I was mixing spring based annotations with open feign annotations. #Headers("Content-Type: multipart/form-data") works with Open feign. Here I am using spring-cloud-openfeign which provides abstraction to Open feign and make it easy to integration with spring framework components.
#FeignClient(url = "http://localhost:5000/")
public interface uploadService {
#RequestMapping(method = RequestMethod.POST, value = "/serviceA/upload" consumes = "multipart/form-data" )
void uploadFile(#RequestPart("file") MultipartFile file);
}
If you have trouble just within the test just use org.springframework.mock.web.MockMultipartFile where you can set contentType as one of argument in construtor.

Spring mvc 4 #PostMapping or #RequestMapping expose rest give 415 response

I am trying to expose rest webservice using spring mvc 4.
With these annotations in controller
#RequestMapping(value = "/services/empservice", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public String testArgument(#RequestBody Employee employee){
System.out.println("employee variable--->"+employee.getEmployeeID());
return String.valueOf(20);
}
#PostMapping(value = "/services/empservices", produces = MediaType.APPLICATION_JSON_VALUE,headers = "content-type=application/x-www-form-urlencoded")
public String testArguments(#RequestBody Employee emploee){
System.out.println("employee variable--->"+employee.getEmployeeID());
return employee.getEmployeeID();
}
The response from WAS 8.5.5 gives 415 Media unsupported Status with
response header
Accept →application/octet-stream, text/plain, application/xml, text/xml, application/x-www-form-urlencoded, application/*+xml, multipart/form-data, /
Accept →application/x-www-form-urlencoded
How to get pass this error and how to set response header for getting application/json with json response
Your issue should be resolved with the next issue of the Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported for #RequestBody answer.
Where necessary to remove annotation #RequestBody

Using Feign #HeaderMap with Springboot 1.5.4.RELEASE does not send headers

I am trying to use feign.HeaderMap annotation to pass a map of HTTP headers in the rest request but these are appearing in the body.
Code below:
#FeignClient(name = "accounts", url = "localhost:8080")
public interface AccountClient {
#RequestMapping(method = RequestMethod.GET, value = "/rest/accounts/get", produces = MediaType.APPLICATION_JSON_VALUE)
Account findOne(#RequestParam("id") String id, #HeaderMap Map headers);
}
You are mixing annotations. When using spring-cloud-netflix you will need to use the Spring annotation #RequestHeader instead.
#RequestMapping(method = RequestMethod.GET,
value = "/rest/accounts/get",
produces = MediaType.APPLICATION_JSON_VALUE)
Account findOne(#RequestParam("id") String id, #RequestHeader Map headers);
In Feign by default, all parameters not annotated will be serialized in the Body.

Resources