How to handle Exception and return proper HTTP code in Spring webflux? - spring-boot

I have a method which gives response using Mono.fromfuture(result) and which throws CustomException with 400 as status.
Now in my service class, when I call that method, the error and code I am throwing there is not getting propagated to my client(postman). Only the message is what I am seeing.
I am getting this below format: -
{
"timestamp": "2019-02-01T11:13:32.748+0000",
"path": "/some_url",
"status": 500,
"error": "Internal Server Error",
"message": "Unable to fetch Response"
}
Expectation (what I want to achieve) : -
{
"timestamp": "2019-02-01T11:13:32.748+0000",
"path": "/some_url",
"status": 400, // (my own status)
"error": "INVALID_ARGUMENT", // (my own error)
"message": "Unable to fetch Response"
}
My Code:-
public Mono<ResponseObject> fetchResponse(arg) {
return Mono.just(somedata which will give exception)
.flatMap(k -> callExternalService(k))
.onErrorMap(e -> Mono.error(
new BusinessException("Unable to fetch Response", e))
*/* e here is giving :-
"code" : 400,
"message" : "Request contains an invalid argument.",
"status" : "INVALID_ARGUMENT" */*
}

Have you looked at the documentation of the Response class?
You can create a Response of your own, using the static methods in the doc, and send it, instead of Mono.error, in the onErrorMap.
You have to return something like below:
ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(klass, Klass.class);
ServerResponse.status(status).build();//read doc and set for yourself
You can also check this link.

Related

How to set message for error reponse status in Spring MVC?

I have a spring mvc handler like this:
#PostMapping("jwtToken")
fun jwtToken(#RequestBody body: JWTToken)
{
val token = body.token
if(token.isNullOrBlank())
throw ResponseStatusException(HttpStatus.UNAUTHORIZED, "Empty token")
}
If i send it an incorrect input, that triggers the exception, i get a reponse body like this:
{
"timestamp": "2020-10-30T03:41:20.305+00:00",
"status": 401,
"error": "Unauthorized",
"message": "",
"path": "/auth/jwtToken"
}
Why is the 'message' field empty in the response when i did assign a message to the exception? How do i set the message field
It might be related to the updated behaviour of the Spring Boot.
https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.3-Release-Notes#changes-to-the-default-error-pages-content
server.error.include-message=always
in .properties should do the trick but I prefer to use my own extended classes like this:
class CustomException(message: String): Exception(message) { ... }

Multipart file (not given condition).Error-400(bad request)

My rest api is.
#PutMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUEpath="/{referenceNumber}")
public void updateCard(#RequestHeader(value = tenantId) String theTenantId,
#PathVariable String referenceNumber,#RequestParam(value = "card")MultipartFile multipartFile,HttpServletRequest request)
I need to check the condition like without browsing the file.
my input format is
Headers :
tenantId : ***
Body : selecting "formdata" (Postman), "multipart-formdata" (AdvancedRestClient)
card : without browsing file
Then i am getting the following error in Postman.
{
"timestamp": 1549351840816,
"status": 400,
"error": "Bad Request",
"exception": "org.springframework.web.multipart.support.MissingServletRequestPartException",
"message": "Required request part 'card' is not present",
"path": "/app-1.5.0/1.5/references/34a236d7-9305-402f-959d-8c83d5ededbb"
}
If i try in the AdvancedRest client with same input
I am getting the different error.
{
"timestamp": 1549352119229,
"status": 415,
"error": "Unsupported Media Type",
"exception": "org.springframework.web.HttpMediaTypeNotSupportedException",
"message": "Content type 'null' not supported",
"path": "/app-1.5.0/1.5/references/34a236d7-9305-402f-959d-8c83d5ededbb"
}
Is there any reason for different outputs and can i check the api without
browsing file.
#PutMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUEpath="/{referenceNumber}")
public void updateCard(#RequestHeader(value = tenantId) String theTenantId,
#PathVariable String referenceNumber,#RequestPart(required = false,value = "card")MultipartFile multipartFile,HttpServletRequest request){
}
User #RequestPart instead of #RequestParam

Set Customize Response for Reactive Web Service using Spring Boot and MongoDB as backend

I am developing reactive-spring-boot web service and also using reactive-mongodb to store data. I want to return my customize response for API. example as below:
[
{
"result": [
{
"code": "",
"data": "",
"error": ""
}
]
}
Sample Method:
#PostMapping(value="/addEmployee")
public Mono<Response> addEmployeeDetails(Employee employee){
Response response = new Response();
if(employee.getEmpID() == null){
return response(getResponse());
}
Repository.save(employee);
return response(getResponse());
}
As you see in the code I have response() method which builds the required response.But it mono gives default response as below:
{
"timestamp": "2018-09-29T16:23:21.287+0000",
"status": 500,
"error": "Internal Server Error",
"message": "Internal Server Error",
"path": "/employee"
}
I am not able to set my own status code and error message.

Google APi Bad Request

i try to implement Passes service of Google Api in our website but we always have error 400 problem
we follow this documentation
Giftcardclass: insert
i use postman for test
POST https://www.googleapis.com/walletobjects/v1/giftCardClass
Request body
{
"kind":"walletobjects#loyaltyObject",
"id":"test2.test",
"classId":"test.test",
"version":12,
"state":"active",
"issuername":"dsadasdasdas",
"barcode":{
"kind":"walletobjects#barcode",
"type":"ean13",
"value":"aaaa",
"alternateText":"aaaa"
}
}
jSon response
{ "error": {
"errors": [
{
"domain": "global",
"reason": "invalidArgument",
"message": "Bad Request"
}
],
"code": 400,
"message": "Bad Request" }
}
from the documentation seems that only id,issuerstate and reviewStatus are required.
Looks like your ids are formatted wrongly, it should be issuer_id.unique_id. See https://developers.google.com/pay/passes/rest/v1/giftcardclass#GiftCardClass.FIELDS.id for reference.

google enterprise license manager api - Unauthorized operation for the given domain

The LicenseAssignments.get api returns 200 OK
Request:
GET https://www.googleapis.com/apps/licensing/v1/product/Google-Apps/sku/Google-Apps-For-Business/user/<email>
Response:
200 OK
- Show headers -
{
"kind": "licensing#licenseAssignment",
"selfLink": "https://www.googleapis.com/apps/licensing/v1/product/Google-Apps/sku/Google-Apps-For-Business/user/<email>",
"userId": "<email>",
"productId": "Google-Apps",
"skuId": "Google-Apps-For-Business"
}
However LicenseAssignments.listForProduct returns "403 Forbidden"
Request:
GET https://www.googleapis.com/apps/licensing/v1/product/Google-Apps/users?customerId=my_customer
Response:
403 Forbidden
- Show headers -
{
"error": {
"errors": [
{
"domain": "global",
"reason": "forbidden",
"message": "Unauthorized operation for the given domain."
}
],
"code": 403,
"message": "Unauthorized operation for the given domain."
}
}
Any idea why I get 403 forbidden for the second request?
This issue got resolved when I used 'domain name' (e.g. something.com) as 'customerId'. This is different from the usual behavior of other Google APIs where 'customerId' is 'my_customer'.
https://www.googleapis.com/apps/licensing/v1/product/Google-Apps/users?customerId=<domain name>

Resources