Customise and remove unrequired fields from Zalando problem reponse body in Spring Boot - spring

I am facing an issue where I throw a Zalando problem error on validation of a field in Spring boot. I customized the response body by extending from AbstractThrowableProblem by invoking the super constructor and passing the required fields.
I set the Status field as BAD_REQUEST and then I pass my custom object to the 'parameters' argument which takes a Map.
Till this point, it's fine. I get a 400 BAD_REQUEST Http status code along with the custom map object in the response body.
The problem now here is that a 'status' field also shows up in the response body which is coming since I set it while calling the super constructor.
I want to know how to just have 400 in the Http Status code section only and not in the response body. I just need my custom map object in the response body.
Actual response:
Response Http status code - 400 BAD_REQUEST
Response body -
{
"status": 400,
"appError": "The name field that you filled in has Invalid special characters."
}
Expected response:
{
"appError": "The name field that you filled in has Invalid special characters."
}
The Zalando problem class I wrote is as below:
class MyAppZalandoProblem extends AbstractThrowableProblem {
Map<String, Object> myMap = new HashMap<>();
myMap.put("appError", "The name field that you filled in has Invalid special characters.");
MyAppZalandoProblem() {
super(null, null, Status.BAD_REQUEST, null, null, null, myMap);
}
}

Short answer
You simply can't.
It's not the recommended way to return an HTTP problem: RFC7807
By the way, The Zalando Problem library maintainers have refused to allow such customization.

Related

Null value received when i send a request contained an array of enum with Postman to Spring Boot

Postman Request
RequestDTO + response eSexes null
ENUM class ESex
I don't know for what reason, but i solved it changing the name of the variable in the DTO from "eSexes" to "sessi"...very weird

POST request response being sent in weird format

I intend to send my server response in the following format
Api Doc
I did the following
headersR.add("response_code", "OK");
headersR.add("cmd_code", "SET_FK_NAME");
headersR.add("trans_id", Long.toString(System.currentTimeMillis()/1000000));
JSONPObject map1 = new JSONPObject("fk_name", "jj");
return new ResponseEntity<>(map1, headersR, HttpStatus.OK);
I was getting a negative response from the other side so I checked Wireshark(Had a hard time logging my response body). And I got this in Wireshark.
Wirehark Screenshot
The response body is Definitely not JSON.
How can I fix this?
The response body fk_name("jj") is not JSON, it's JSONP -- Browser would take the function name fk_name and try to execute it with "jj" as parameter.
The root cause is you are using JSONPObject, whose constructor accepts 2 parameters: a function name, and the data value. Not the expected JSON key and value.
To fix this issue and return {"fk_name":"jj"}, remove the JSONPObject stuff and use code as follow:
return new ResponseEntity<>("{\"fk_name\":\"jj\"}", headersR, HttpStatus.OK);

Spring receiving empty body

I'm using Spring for my backend. I have the following code:
#RequestMapping(value = "/test", method = RequestMethod.POST)
#CrossOrigin
public void test(HttpServletRequest request) {
System.out.println(request.getParameterMap().size());
System.out.println(new JSONObject(request.getParameterMap()));
}
When I send JSON data using Postman, I get a map of all the parameters I've sent.
But when I'm making the same call from my website, I get an empty map with size 0. I do not get any error or exception on both front and back sides.
What could be the reason?
Thank you
Most probably getParameterMap() is really empty in your case, because parameters are not passed as query, but as a body (content) of HTTP request when it is sent from your web-site.
It can also be affected by the Content-Type and Accept headers of the HTTP request.
According to official documentation ServletRequest.getParameterMap() returns:
For HTTP servlets, parameters are contained in the query string or posted form data.
Usually "posted form data" implies: HTTP header Content-Type: application/x-www-form-urlencoded and URL encoded name-value pairs of parameters in the content of HTTP request.
If your web-site sends application/json, any other content type, or does not define content type at all, it might not be properly mapped into the request parameters by servlet container. In this case you should look into the body of HTTP request (ServletRequest.getReader()) to get the payload, or let Spring MVC do that (e.g. #RequestBody annotation).

Different response from a controller method based on HTTP Response code

How do you write a controller method which can either return a View or HTTP response status code based on if its 200 then view else the response status code.
#RequestMapping(value="/",method=RequestMethod.GET)
public String showLanding()
{
return View.Landing;
}
I want to handle in case of 401, 403, 500 etc. just status code should be returned instead of view.
To return the 403- Unauthorized status code,
#RequestMapping(value="/",method=RequestMethod.GET)
public String showLanding()
{
return HttpStatus.UNAUTHORIZED;
}
See this:
http://docs.spring.io/spring/docs/3.1.x/javadoc-api/org/springframework/http/HttpStatus.html?is-external=true
How to respond with HTTP 400 error in a Spring MVC #ResponseBody method returning String?
You could also check out the #ResponseStatus annotation as well as ResponseEntity (for more dynamic scenarios)
I'm far from suggesting that you should do flow control with Exceptions - but those HTTP statuses are errors and exceptions. So you might want to throw business exceptions from your controller methods and then handle those using #ExceptionHandlers.
You can also target a subset of Controllers and assist those with Exception handling using #ControllerAdvice.

Spring mvc controller null return handler

#RequestMapping(method = RequestMethod.GET)
#ResponseBody
public List<Country> getListOfCountries() {
return countryService.listAll();
}
It displays a json view of the object but if the service return null, then I want to display an error message, Any suggestions pls?
First of all, even if this does not directly answer the question, your objects should never ever return null instead of empty collections - you can find the reasoning in Effective Java 2nd Edition, Item 43 / p.201
So, if the situation when no countries were found is normal it must be processed by the client JS code that will check the count and display the respective message.
If something has gone wrong you can throw an exception(as Biju has pointed out +1) - I believe that it's the service who should throw the exception because it knows the reason why it happened, and not to return null anyway.
I'd like to add that in Spring 3.2(in pre Spring 3.2 returning response body is complicated) you can set an #ExceptionHandler that will both return JSON and set the HTTP status code which can be later processed by the client. I think that returning a custom JSON response with some error code is most optimal here.
#RequestMapping("/test")
#ResponseBody
public List<Country> getListOfCountries() {
//assuming that your service throws new NoCountriesFoundException();
//when something goes wrong
return countryService.listAll();
}
#ExceptionHandler(NoCountriesFoundException.class)
ResponseEntity<String> test() {
return new ResponseEntity<String>(
"We are sorry, our server does not know any countries yet.",
HttpStatus.I_AM_A_TEAPOT );
}
Then in the JS code, you can do specific processing depending on the returned status code.
Also, to avoid declaration of the same #ExceptionHandler in different controllers, in Spring 3.2 you can put #ExceptionHandler inside a #ControllerAdvice annotated class.
For details, see http://static.springsource.org/spring/docs/current/spring-framework-reference/htmlsingle/#mvc-exceptionhandlers and http://www.springsource.org/node/3738 for 3.2 specific things
You have a couple of options I think:
If you return a null back, it will be returned as an empty string "", you can probably look for that and handle it.
Return a wrapper type on top of your list, this way if the wrapped list is null something like this will be returned back to the client {"countries":null} which can be more easily handled at the javascript end.
Throw an exception, which will propagate as a 500 status code back to the client, you can then have an error handler on the javascript side to handle this scenario.

Resources