SpringBoot response charset errors - java

i got some problems with my SpringBoot REST Controller. This simply does a http GET call to our database and should return a simple String / json. when i call the URL simply in my browser or via my angular 3 app, the response has some charset errors and i don't know, how to fix them.
I suggest, it is a UTF-8 problem.
First to show you the output:
this is how it comes from the Controller: MeinekestraÃe
and it should be Meinekestraße
here is a part of my SpringBoot Controller:
#Controller
public class RecieverController {
#Value("${server}")
private String server;
#Value("${user.token}")
private String token;
#RequestMapping(value="/reciever", method=RequestMethod.GET, produces = "text/plain;charset=UTF-8")
#ResponseBody
#CrossOrigin(origins = "http://localhost:4200", maxAge = 3600)
public String getRecieverData(
#RequestHeader(value="Accept") String accept,
#RequestHeader(value="Host") String host) {
final String url = server + "/rest/client/profile";
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
headers.set("Auth-Token", token); // user_token
HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, entity, String.class);
return response.getBody();
}}
I tried the following things, but nothing changed in the output.
spring.http.encoding.charset=UTF-8
spring.http.encoding.enabled=true
spring.http.encoding.force=true
or this
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters()
.add(0, new StringHttpMessageConverter(Charset.forName("UTF-8")));
any other ideas what could be the problem? the database isnt the issue. Everything is stored correctly there.
Edit:
this is the screenshot of the header from the output
and a part from the json output:
The Problem could be solved by adding both
spring.http.encoding.charset=UTF-8
spring.http.encoding.enabled=true
spring.http.encoding.force=true
and this
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters()
.add(0, new StringHttpMessageConverter(Charset.forName("UTF-8")));
Thanks #dienerd for helping me via chat

For the ones looking for a way to force encoding request/response in #RestController in a Spring Boot project.
spring.http.encoding.charset=UTF-8
spring.http.encoding.enabled=true
spring.http.encoding.force=true
is deprecated, in your application.yaml or application.properties use the following:
server.servlet.encoding.charset=UTF-8
server.servlet.encoding.force=true
This did the trick for me.

Related

PostForEntity: 415 Unsupported Media Type

In our project, we call an external API with postForEntity and receive the following: error:org.springframework.web.server.ResponseStatusException: 415 UNSUPPORTED_MEDIA_TYPE "Could not determine reason or message. Plain body: ""
final ActionDto actionDto = new ActionDto ().setRequestId(requestId);
final ResponseEntity<ActionResponseDto> response = restTemplate.postForEntity(url, actionDto, ActionResponseDto.class);
I managed to fix this error by using exchange instead of postForEntity and adding a media type:
final HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
val entity = new HttpEntity(actionDto , headers);
final ResponseEntity<ActionResponseDto> response =
restTemplate.exchange(
url,
HttpMethod.POST,
entity,
ActionResponseDto.class);
My question is the following, could you give me some hints why before with postForEntity it worked and now suddenly it doesn't?
I also checked the external API and the method looks like bellow, and nothing has changed:
#PostMapping("/action/start")
#ResponseStatus(HttpStatus.OK)
#Operation(summary = "Start the action")
public ResponseEntity<ActionResponseDto> startAction(#RequestBody final ActionDto requestDto) {
.....
}
Could it be due to some dependencies? This error is very strange...
Thank you! :)

Error in getting image from Graph API in spring-boot with resttemplate

I am using the graph api:
GET /users/{id | userPrincipalName}/photo/$value
to get the particular user's profile photo with my access token. In postman I am able to see the image using the above get call.
In my spring-boot application I am using like below:
final ResponseEntity<Object> profilePicture = restTemplate.exchange(graphUrl, HttpMethod.GET, new HttpEntity<>((header)), new ParameterizedTypeReference<>() {});
I am getting below error:
Could not extract response: no suitable HttpMessageConverter found for response type [class java.lang.Object] and content type [image/jpeg]
I have defined RestTemplate like:
#Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
Could someone please help me with this?
You need to add an appropriate MessageConverter to your RestTemplate.
Something like:
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new ByteArrayHttpMessageConverter());
ResponseEntity<byte[]> response = restTemplate.exchange(graphUrl,
HttpMethod.GET, new HttpEntity<>((header)), byte[].class);
You can read more on this subject here: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/http/converter/HttpMessageConverter.html

Spring : ResponseEntity<String> return empty value

I'm working with a small module with Spring (5.0.8) and i'm looking to make some logs for debugging purposes.
My ResponseEntity return an empty value and after some research, I can't figure out why.
I've been going through some post like this one Spring: Returning empty HTTP Responses with ResponseEntity<Void> doesn't work but i haven't found a suitable solution for my case.
private RestTemplate buildRestTemplate() {
RestTemplate restTemplate = buildBasicRestTemplate();
restTemplate.getInterceptors().add(new BasicAuthorizationInterceptor(
REST_ADMIN_USERNAME,
REST_ADMIN_PASSWORD));
return restTemplate;
}
RestTemplate restTemplate = buildRestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<ActivityLogBean> entity = new HttpEntity<ActivityLogBean>(headers);
String resourceUrl = "http://localhost:8080/rest/data/timestamp"
ResponseEntity<String> response = restTemplate.exchange(uriWithParams, HttpMethod.GET, entity, String.class);

Spring Boot RestTemplate exchange 400 bad request

I have a problem with Spring Boot RestTemplate exchange.
I have the following code:
#RequestMapping(path = "/add")
public #ResponseBody String addFromTo () {
String apikey = "";
String baseurl = "http://demowebshop.webshop8.dk/admin/WEBAPI/v2/orders?start=2018-10-05T20%3A49%3A41.745Z&end=2018-10-15T20%3A49%3A41.745Z&api_key=" + apikey;
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
headers.setBasicAuth("", apikey);
HttpEntity<String> request = new HttpEntity<String>(" ", headers);
ResponseEntity<OrderResponse> response = restTemplate.exchange(baseurl, HttpMethod.GET, request, OrderResponse.class);
return "Some text.";
}
What I want is the equivalent of:
curl -X GET --header 'Accept: application/json' --header 'Authorization: Basic {encodedapikey}' 'http://demowebshop.webshop8.dk/admin/WEBAPI/v2/orders?start=2018-10-06T06%3A43%3A40.926Z&end=2018-10-16T06%3A43%3A40.926Z&api_key={apikey}'
I've tried using Postman with the exact same URL, and adding Basic Auth with the apikey, and an 'Accept: application/json' header, and that works fine, but when I run this code, I get the error message:
There was an unexpected error (type=Internal Server Error, status=500).
400 Bad Request
EDIT:
Pastebin link to the exception thrown by the program:
https://pastebin.com/jdYJ2nv7
In your curl request you are using an apikey and encodedapikey. Whereas in your Java code you don't. Next to that you are also passing an encoded URL as the URL to use. This will result in encoding the encoded URL again. So don't do that. Instead use a URL with placeholders and supply values for them.
#RequestMapping(path = "/add")
public #ResponseBody String addFromTo () {
String apikey = "";
String baseurl = "http://demowebshop.webshop8.dk/admin/WEBAPI/v2/orders?start={start}&end={end}&api_key={apikey}";
Map<String, Object> parameters = new HashMap<>();
parameters.put("start", "2018-10-05T20:49:41.745Z");
parameters.put("end", "2018-10-16T06:43:40.926Z");
parameters.put("apikey", apikey);
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
headers.setBasicAuth("", apikey);
ResponseEntity<OrderResponse> response = restTemplate.getForEntity(baseurl, OrderResponse.class, parameters);
return "Some text.";
}
The code above uses a proper parameterized URL together with a map containing values for the placeholders. Notice that those aren't encoded, as that will be handled by Spring!. Finally you can simply use the getForEntity method to get the result instead of the exchange method.
A final suggestion, Spring Boot already configures a RestTemplate which you can (re)use. You don't need to create a RestTemplate each time you need one (it is quite a heavy object to create, and after creation it is thread safe so it is enough to have a single instance).
public YourClassCOnstructor(RestTemplateBuilder builder) {
this.restTemplate = builder.basicAuthorization("", apikey).build();
}
Ofcourse you can also put this in an #Bean method and inject the specific RestTemplate into your class.
HttpHeaders.setBasicAuth(String, String) is used for username and password only, not for basic token.
If you want to use basic token try something like headers.add("Authorization", "Basic " + apiKey) instead of headers.setBasicAuth(...)

How to extract HTTP status code from the RestTemplate call to a URL?

I am using RestTemplate to make an HTTP call to our service which returns a simple JSON response. I don't need to parse that JSON at all. I just need to return whatever I am getting back from that service.
So I am mapping that to String.class and returning the actual JSON response as a string.
RestTemplate restTemplate = new RestTemplate();
String response = restTemplate.getForObject(url, String.class);
return response;
Now the question is -
I am trying to extract HTTP Status codes after hitting the URL. How can I extract HTTP Status code from the above code? Do I need to make any change into that in the way I doing it currently?
Update:-
This is what I have tried and I am able to get the response back and status code as well. But do I always need to set HttpHeaders and Entity object like below I am doing it?
RestTemplate restTemplate = new RestTemplate();
//and do I need this JSON media type for my use case?
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
//set my entity
HttpEntity<Object> entity = new HttpEntity<Object>(headers);
ResponseEntity<String> out = restTemplate.exchange(url, HttpMethod.GET, entity, String.class);
System.out.println(out.getBody());
System.out.println(out.getStatusCode());
Couple of question - Do I need to have MediaType.APPLICATION_JSON as I am just making a call to url which returns a response back, it can return either JSON or XML or simple string.
Use the RestTemplate#exchange(..) methods that return a ResponseEntity. This gives you access to the status line and headers (and the body obviously).
getStatusCode()
getHeaders()
If you don´t want to leave the nice abstraction around RestTemplate.get/postForObject... methods behind like me and dislike to fiddle around with the boilerplate stuff needed when using RestTemplate.exchange... (Request- and ResponseEntity, HttpHeaders, etc), there´s another option to gain access to the HttpStatus codes.
Just surround the usual RestTemplate.get/postForObject... with a try/catch for org.springframework.web.client.HttpClientErrorException and org.springframework.web.client.HttpServerErrorException, like in this example:
try {
return restTemplate.postForObject("http://your.url.here", "YourRequestObjectForPostBodyHere", YourResponse.class);
} catch (HttpClientErrorException | HttpServerErrorException httpClientOrServerExc) {
if(HttpStatus.NOT_FOUND.equals(httpClientOrServerExc.getStatusCode())) {
// your handling of "NOT FOUND" here
// e.g. throw new RuntimeException("Your Error Message here", httpClientOrServerExc);
}
else {
// your handling of other errors here
}
The org.springframework.web.client.HttpServerErrorException is added here for the errors with a 50x.
Now you´re able to simple react to all the StatusCodes you want - except the appropriate one, that matches your HTTP method - like GET and 200, which won´t be handled as exception, as it is the matching one. But this should be straight forward, if you´re implementing/consuming RESTful services :)
If you want all the HTTPStatus from a RestTemplate including 4XX and 5XX, you will have to provide an ResponseErrorHandler to the restTemplate, since the default handler will throw an exception in case of 4XX or 5XX
We could do something like that :
RestTemplate restTemplate = new RestTemplate();
restTemplate.setErrorHandler(new DefaultResponseErrorHandler() {
#Override
public boolean hasError(HttpStatus statusCode) {
return false;
}
});
ResponseEntity<YourResponse> responseEntity =
restTemplate.getForEntity("http://your.url.here", YourResponse.class);
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.XXXX);
private RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.exchange(url,HttpMethod.GET, requestEntity,String.class);
response contains 'body', 'headers' and 'statusCode'
to get statusCode : response.getStatusCode();
exchange(...) works but if you want less code, you can use
org.springframework.boot.test.web.client.TestRestTemplate.getForEntity(...)
which returns an Entity containing StatusCode. Change your example code to this:
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
HttpStatus statusCode = response.getStatusCode();
To test it you can use this snippet from my unit test:
ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
assertResponseHeaderIsCorrect(response, HttpStatus.OK);
/**
* Test the basics of the response, non-null, status expected, etc...
*/
private void assertResponseHeaderIsCorrect(ResponseEntity<String> response, HttpStatus expectedStatus) {
assertThat(response).isNotNull();
assertThat(response.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_JSON_UTF8);
assertThat(response.getStatusCode()).isEqualTo(expectedStatus);
}
There can be some slightly trickier use cases someone might fall in (as I did). Consider the following:
Supporting a Page object in order to use it with RestTemplate and ParameterizedTypeReference:
RestPageResponse:
import java.util.ArrayList;
import java.util.List;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
public class RestResponsePage<T> extends PageImpl<T>{
private static final long serialVersionUID = 3248189030448292002L;
public RestResponsePage(List<T> content, Pageable pageable, long total) {
super(content, pageable, total);
}
public RestResponsePage(List<T> content) {
super(content);
}
public RestResponsePage() {
super(new ArrayList<T>());
}
}
Using ParameterizedTypeReference will yield the following:
ParameterizedTypeReference<RestResponsePage<MyObject>> responseType =
new ParameterizedTypeReference<RestResponsePage<MyObject>>() {};
HttpEntity<RestResponsePage<MyObject>> response = restTemplate.exchange(oauthUrl, HttpMethod.GET, entity, responseType);
Calling #exchange:
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
HttpEntity<?> entity = new HttpEntity<>(headers);
response = restTemplate.exchange("localhost:8080/example", HttpMethod.GET, entity, responseType);
Now here is the "tricky" part.
Trying to call exchange's getStatusCode will be impossible because the compiler, unfortunately, will be unaware of the "intended" type of response.
That is because generics are implemented via type erasure which removes all information regarding generic types during compilation (read more - source)
((ResponseEntity<RestResponsePage<MyObject>>) response).getStatusCode()
In this case, you have to explicitly cast the variable to the desired Class to get the statusCode (and/or other attributes)!
Putting this much of code is enough for me
HttpStatus statusCode = ((ResponseEntity<Object>) responseOfEsoft).getStatusCode();
You can use this solution
RestTemplate restTemplate = new RestTemplate();
final String baseUrl = "http://www.myexampleurl.com";
URI uri = new URI(baseUrl);
ResponseEntity<String> result = restTemplate.getForEntity(uri, String.class);
//get status code
int statuCode = result.getStatusCodeValue();
Was able to solve this through:
HttpEntity<Object> entity = restTemplate.getForEntity(uri, Object.class);
ResponseEntity<String> result = restTemplate.exchange(uri, HttpMethod.GET, entity, String.class);
System.out.println(result.getStatusCode());

Categories

Resources