I am working on developing RESTful service on Java using Spring framework. If exception occurs in my services layer i throw an exception bound to Http status code. For example when user's authentication fails i send response with 401 status code.
return new ResponseEntity<>(HttpStatus.valueOf(statusCode));
I would like to explain to RESTful service consumer what is wrong with his request sending not only the code but also textual explanation. I can do this either by adding custom message to response body or by replacing default response phrase. For example replace Unauthorized for 401 with User does not exist or Incorrect password.
The problem is HttpStatus from org.springframework.http is enum and error codes are bound to textual response phrases.
Can i somehow override those response phrases or i need another approach?
And is it good practice to replace default response phrase or it would be better to put explanation message to response body?
This should work:
First you can bound the request method to the type it produces by adding
produces = {MediaType.TEXT_PLAIN} to your #RequestMapping where MediaType is from import javax.ws.rs.core.MediaType this will produce text plain response.
Then you can return the following:
return new ResponseEntity<>(message, HttpStatus.UNAUTHORIZED); where message is the text message you want to show.
Related
I know sending a body with a GET request isn't the best idea but I'm trying to consume an existing API which requires it.
Sending a body with POST is straight-forward:
webClient.post()
.uri("/employees")
.body(Mono.just(empl), Employee.class)
.retrieve()
.bodyToMono(Employee.class);
It won't work with webClient.get() though, because while the post() method returns a WebClient.RequestBodyUriSpec, the get() method returns WebClient.RequestHeadersUriSpec<?>, which doesn't seem to allow any body definitions.
I've found a workaround for Spring RestTemplate here: RestTemplate get with body,
but had no luck finding any for the new WebClient.
While the other responses are correct that you shouldn't use a body with a GET request, that is not helpful when you do not own, or cannot change the already existing method you are calling.
The problems is WebClient#get returns a WebClient.RequestHeadersUriSpec which does not provide a way for us to set the body.
WebClient#post returns a WebClient.RequestBodyUriSpec which does provide us a way to set the body but will cause us to use the wrong HTTP method, POST instead of GET.
Thankfully for us stuck in this situation there is WebClient#method which returns a WebClient.RequestBodyUriSpec and allows us to set the HTTP method.
webClient.method(HttpMethod.GET)
.uri("/employees")
.body(Mono.just(empl), Employee.class)
.retrieve()
.bodyToMono(Employee.class);
You may still run into issues in your testing libraries though...
A GET reques has no body. It is forbidden (well, not forbidden, but not used at all) by the HTTP specification. You have two approaches here:
Do a POST. It is there just for that.
Use a query string and pass the data in that part of the URL.
Of course, you can attach the needed fields and pass a payload to the GET request, but it will probably be ignored, or worse, identified as an error and rejected by the server, before your served code has access to it. But if you are passing data to the server to do some processing with it, then POST is what you need to use.
Extracted from RFC-7231. HTTP 1.1. Semantics and code:
A payload within a GET request message has no defined semantics;
sending a payload body on a GET request might cause some existing
implementations to reject the request.
(markup is mine)
Reasons for this are, mainly, that a GET method must be idempotent, producing the same output for the same URL, if repeated. POST doesn't have these requirements, so POST is your friend.
First of all, give thanks for reading my question and try to help me and apologize for my English.
I'm new with Spring and I have this message:
A servlet request to the URI
http://localhost:8080/backend/v1/streetviewer/search-street?url=backend2?busqueda=name%20street&idioma=es-es%26cantidad=10
contains form parameters in the request body but the request body has been consumed by the servlet or a servlet filter accessing the request parameters. Only resource methods using #FormParam will work as expected. Resource methods consuming the request body by other means will not work as expected.
My backend send a request to backend2 with one parameter (url), but that url contains 3 parameters. I understand that is reason why say that.
But I was reading that #FormParam is used for POST requests and I'm using #QueryParam.
#GET
#Path(ApiPath.PATH_BACKEND2)
public String getDataFromProdServer(#QueryParam(ApiParam.PARAM_URL) final String externalUrl ) {
return mapService.ServerRequest(externalUrl);
}
How can solve it??
To be said you are actually using JAX-RS Implementation, from backend2 I asume it is a separate service so I suggest you to use Spring Implementations for consuming the API. #RequestMapping/#GetMapping and so..
Coming to the question (With Spring Implementation)
#GetMapping(ApiPath.PATH_BACKEND2)
public String getDataFromProdServer(#RequestParam(ApiParam.PARAM_UR) final String externalUrl) {
return mapService.serverRequest(externalUrl);
}
There are multiple ways to send custom message in error response of rest api call.
Which is the best way out of these :
1.One way is to use io.swagger.annotations like
#ApiResponses(value = { #ApiResponse(code = 500, message = "error message", response=ErrorDescription.class) })
above method signature.
2.Another way is to define #ControllerAdvice over global exception hanlder.
Which is the better way of two.
Thanks
Your first approach with the swagger annotation won't handle your errors in your application. It's just for documentation purposes so that you can see how your API behaves in an error case. With this annotation, you customize your swagger-ui.html page for your REST endpoint and map the error code to a specific response object and add a custom description for your clients.
To really handle e.g. exceptions with self-defined response types and message you can use #ControllerAdvice and define the result types and messages. In addition, I would also use the Swagger annotation to write some text about the error case and tell the client which response object he can expect.
The following blog post might help you for writing your #ControllerAdvice clas: http://niels.nu/blog/2016/controller-advice-exception-handlers.html
Suppose I have REST endpoint which gives me properties of given media ID using GET. If user calls the endpoint with wrong HTTP verb, like POST or DELETE, I want to give descriptive error message saying "Method is not supported". I am using JAX-RS for REST mapping. JAX-RS just throws 404 with no descriptive error message.
What is the proper way of handling this scenario? Are there more descriptive ways of returning an error?
I'm updating legacy code that uses the exchange method of Spring 3.1 Framework's RestTemplate class. I came across what appears to be a major omission of detail. When the rest client with which I am attempting to communicate returns a 400 status code, a HttpClientErrorException is thrown but there is no response body to provide detail as to why the server rejected the request. There looks like there is no way to retrieve the response body which would provide very helpful information.
I do not need to figure out what is wrong in my calling code as I have already done that. I just would like to know if there is some way I could access and log the body of the HTTP response if an error occurs on the call.
The response body is actually a property on HttpClientErrorException. It can be accessed via the following two accessors which it inherits from its parent class HttpStatusCodeException:
public byte[] getResponseBodyAsByteArray()
public String getResponseBodyAsString()
Cast your HttpClientErrorException e to HttpStatusCodeException:
((org.springframework.web.client.HttpStatusCodeException) e).getResponseBodyAsString()