org.springframework.web.client.HttpClientErrorException: 415 null(Spring Resttemplate) - java

I try to get list of entity with using rest template, but I get 415 error in line:
ResponseEntity<List<ResponseOrderDto>> responseEntity = rest.exchange
My implementation:
RestTemplate rest = new RestTemplate();
rest.getInterceptors().add((request, body, execution) -> {
ClientHttpResponse response = execution.execute(request,body);
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
response.getHeaders().add("Bearer", contentToken);
return response;
});
ResponseEntity<List<ResponseOrderDto>> responseEntity = rest.exchange(
ORDER_SERVICE_URL + "/by-user",
HttpMethod.GET,
null,
new ParameterizedTypeReference<List<ResponseOrderDto>>() {
});
How fix this error?

415 means unsupported content type, so the Content-type header is not correctly set.
Based on your code, I think that the request needs JSON Content-Type header, but you set the content-type header on the response instead of the request.
Change your interceptor to be something like this:
rest.getInterceptors().add((request, body, execution) -> {
request.getHeaders().setContentType(MediaType.APPLICATION_JSON);
request.getHeaders().add("Bearer", contentToken);
ClientHttpResponse response = execution.execute(request, body);
return response;
});
To set the headers at the right time to the request

Related

Sending same request headers into the response headers cause infinity loop and incorrect json response Spring boot

I want to return the same request headers in my controller response but if I do this and infinity wait look occurs when trying to test with postman
I have this controller
#PostMapping("/yy")
public ResponseEntity<ClientOutput> myTest(#RequestHeader HttpHeaders headers,
#RequestBody ClientInput clientInput) {
return new ResponseEntity<>(new ClientOutput(), headers, HttpStatus.OK);
}
this cause an infinity waiting loop when I try to test it with postman, how can I return the same headers that I get from my request in my response,
And it also produce an incomplete response when I try with this controller
#PostMapping("/uu")
public ResponseEntity<ClientOutput> myTestTwo(#RequestHeader HttpHeaders headers,
#RequestBody ClientInput clientInput) {
return new ResponseEntity<>(ClientOutput.builder()
.error(Error.builder()
.code("401")
.title("Error")
.message("A error happened")
.build())
.build(), headers, HttpStatus.UNAUTHORIZED);
}
instead of returning my error DTO it returns this incomplete JSON
{
"name": null,
"error": {
"code": "401",
"title": "Error",
I just want to return the same request headers in my response
Postman is sending by default the Header Content-Length and it is calculated for the request. Since your code is just taking the Content-Length header of the request and returns it, it will not match the real length of the response.
Removing the request header Content-Length in Postman will fix the issue that your response is an incomplete JSON structure.
In Postman open Headers tab for request and make sure auto-generated headers are not hidden. Then you can uncheck Content-Length header.

How to log spring webclient request and response body?

added an ExchangeFilterFunction to WebClient which logs request and response but while logging, was unable to log request and response body as a string or JSON. It prints as an object
Tried different castings and retrieving the body as a string using bodyToMono, toEntity but they return an object and not string exactly.
logRequest(clientRequest.url(), clientRequest.method(), clientRequest.headers(), clientRequest.body());
Mono<ClientResponse> response = exchangeFunction.exchange(clientRequest);
ClientResponse clientResponse = response.block();
logResponse(clientResponse.statusCode(), clientResponse.headers(), clientResponse.toString(), clientResponse);
return response;
}```
```private void logRequest(URI uri, HttpMethod method, HttpHeaders httpHeaders, BodyInserter<?, ? super ClientHttpRequest> body) {
log.info("Request: {}",
LogVar.with("Body", body)
);
}
private void logResponse(HttpStatus statusCode, Headers headers, String body, ClientResponse extractor) {
log.info("Response: {}",
, LogVar.with("Body", extractor.bodyToMono(String.class))
);
}```
Expecting Json OR XML whatever the request/response is, to be logged as a string.

Spring Rest template overwriting Authorization header value

I am making rest call like below:
REST_TEMPLATE.exchange(
external_rest_url,
HttpMethod.POST,
new HttpEntity<>(dto, getHeaders()),
Map.class)
and my headers are as below:
private HttpHeaders getHeaders() {
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("User-Agent","Spring's RestTemplate");
headers.set(HttpHeaders.AUTHORIZATION, "some value");
return headers;
}
when I run my code the header HttpHeaders.AUTHORIZATION is getting replaced with undefined
See request header in snapshot below from network logs:
Do anyone know why spring is behaving like this or specifically spring-web:5.0.5 jar. I tried changing the version of jar as well but result is same.
Springboot version I use is 2.0.x.
you can add an interceptor to your RestTemplate if you need to add the same headers to all requests:
public void sampleHeader(final RestTemplate restTemplate){
//Add a ClientHttpRequestInterceptor to the RestTemplate
restTemplate.getInterceptors().add(new ClientHttpRequestInterceptor(){
#Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
request.getHeaders().set(HttpHeaders.AUTHORIZATION, "some value");//Set the header for each request
return execution.execute(request, body);
}
});
}

How to change response body in intercept (Using retrofit 2)

I read thousand of answers and try to a lot of way but doesn't work.
I really need to change response body when get "401". Because server response is different from other general response when unauthorized.
I'm using retrofit 2. To catch response i'm using Interceptor:
Request original = chain.request();
Request.Builder requestBuilder = original.newBuilder()
.header("authorization", getAccessToken(context));
Request request = requestBuilder.build();
Response response= chain.proceed(request);
if (response.code()==401) {
MediaType contentType = response.body().contentType();
ResponseBody body = ResponseBody.create(contentType, CommonFunctions.getUnAuthorizedJson(context).toString());
return response.newBuilder().body(body).build();
}else{
return response;
}
But still body doesn't change on client.enque method.
You can change body in this way, but Retrofit will eventually see 401 and throw HttpException with standart message, what can be misleading
check that you get your body right:
val errorConverter: Converter<ResponseBody, ErrorResponse> =
retrofit.responseBodyConverter(
ErrorResponse::class.java,
emptyArray()
)
val errorResponse = httpException
.response()
?.errorBody()
?.let (errorConverter::convert)

What is the difference between ResponseEntity<T> and #ResponseBody?

I have a simple handler in my controller which returns a message
#RequestMapping(value = "/message")
#ResponseBody
public Message get() {
return new Message(penguinCounter.incrementAndGet() + " penguin!");
}
At the same time I can use something like this
#RequestMapping(value = "/message")
ResponseEntity<Message> get() {
Message message = new Message(penguinCounter.incrementAndGet() + " penguin!");
return new ResponseEntity<Message>(message, HttpStatus.OK);
}
What is the difference betweet this two approaches? Let's not take into account HttpStatus :)
ResponseEntity will give you some added flexibility in defining arbitrary HTTP response headers. See the 4th constructor here:
http://docs.spring.io/spring/docs/3.0.x/api/org/springframework/http/ResponseEntity.html
ResponseEntity(T body, MultiValueMap<String,String> headers, HttpStatus statusCode)
A List of possible HTTP response headers is available here:
http://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Responses
Some commonly-used ones are Status, Content-Type and Cache-Control.
If you don't need that, using #ResponseBody will be a tiny bit more concise.
HttpEntity represents an HTTP request or response consists of headers and body.
// Only talks about body & headers, but doesn't talk about status code
public HttpEntity(T body, MultiValueMap<String,String> headers)
ResponseEntity extends HttpEntity but also adds a Http status code.
// i.e ResponseEntity = HttpEntity + StatusCode
public ResponseEntity(T body, MultiValueMap<String,String> headers, HttpStatus statusCode)
Hence used to fully configure the HTTP response.
For Ex:
#ControllerAdvice
public class JavaWebExeptionHandler {
#Autowired
ExceptionErrorCodeMap exceptionErrorCodeMap;
#ExceptionHandler(RuntimeException.class)
public final ResponseEntity<ExceptionResponseBody> handleAllExceptions(Exception ex) {
Integer expCode = exceptionErrorCodeMap.getExpCode(ex.getClass());
// We have not added headers to response here, If you want you can add by using respective constructor
return new ResponseEntity<ExceptionResponseBody>(new ExceptionResponseBody(expCode, ex.getMessage()),
HttpStatus.valueOf(expCode));
}
}
#ResponseBody indicates that return value of method on which it is used is bound to the response body
(Mean the return value of method is treated as Http response body)
ResponseEntity<> is a generic class with a type parameter, you can specify what type of object to be serialized into the response body.
#ResponseBody is an annotation, indicates that the return value of a method will be serialized into the body of the HTTP response.
you can set headers using ResponseEntity<>
#ResponseEntity represents a response which includes headers, body and status code.
#ResponseBody only returns the body of the response.

Categories