I have simple java spring method for creating object
RestTemplate restTemplate = new RestTemplate();
Address address = restTemplate.getForObject(url, Address.class);
But the server responds me JSON string with wrong Content-Type: text/plain instead of application/json (checked in Postman). And I get the exception:
Could not extract response: no suitable HttpMessageConverter found for response type [class Address] and content type [text/plain;charset=utf-8]
So I think, I need change response header Content-Type to right application/json, that MappingJackson2HttpMessageConverter find out JSON string and run code as well.
After trying for an hour, I found a short and easy way.
Json converter by default supports only "application/json". We just override it to support "text/plain".
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
// support "text/plain"
converter.setSupportedMediaTypes(Arrays.asList(TEXT_PLAIN, APPLICATION_JSON));
RestTemplate template = new RestTemplate();
template.getMessageConverters().add(converter);
// It's ok now
MyResult result = tmp.postForObject("http://url:8080/api",
new MyRequest("param value"), MyResult.class);
Thank you for help!
In case I can't change response's header. I create new response object with right header.
ClientHttpRequest clientHttpRequest = new SimpleClientHttpRequestFactory().createRequest(URI.create(str), org.springframework.http.HttpMethod.GET);
final ClientHttpResponse clientHttpResponse = clientHttpRequest.execute();
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
Address address = new Address();
//It always true, because service always returns 200 OK
if (clientHttpResponse.getStatusCode() == HttpStatus.OK) {
address = (Address) converter.read(address.getClass(), new HttpInputMessage() {
public InputStream getBody() throws IOException {
return clientHttpResponse.getBody();
}
public HttpHeaders getHeaders() {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.putAll(clientHttpResponse.getHeaders());
httpHeaders.put("Content-Type", Collections.singletonList(MediaType.APPLICATION_JSON_VALUE));
return httpHeaders;
}
});
busStop.setNearestAddress(address.toString());
}
I'm sure it isn't simple and good solution, but It works.
To set the content type for your request you could do something like:
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity entity = new HttpEntity(headers);
ResponseEntity<Address> response = restTemplate.exchange(url, HttpMethod.GET, entity, Address.class);
Address address = response.getBody();
Related
I throw when post request via Rest Api, result is
Content-Type: application/json
{
"error": "file content is not in the appropriate format",
"file_name": "15-10-2019-11-19-32_KKK.csv"
}
When I try code on my side, I use the below code
public RestTemplate restTemplateBuilder() {
RestTemplate restTemplate = new RestTemplate(new HttpComponentsClientHttpRequestFactory());
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
ObjectMapper mapper = new ObjectMapper();
mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
converter.setObjectMapper(mapper);
restTemplate.getMessageConverters().add(0, converter);
restTemplate.setErrorHandler(new RestTemplateHandler());
return restTemplate;
}
RestTemplate restTemplate = restTemplateBuilder();
ResponseEntity<FileUploadResponseDTO> serviceResponse = restTemplate.exchange(url, HttpMethod.POST, requestEntity, FileUploadResponseDTO.class);
org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [....FileUploadResponseDTO] and content type [text/html]
Gives a fault. how do I convert?
You can add content-type header to RestTemplate:
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> requestEntity = new HttpEntity<String>(headers);
A server is giving me a response in content-type text/json and I need to consume it into a Java class. I can do that no problem when the server's response is content-type application/json. How can I achieve the same functionality as when I consume an application/json content-type when I consume a text/json content type using Spring Boot?
I've tried creating an HttpHeaders object and then the setContentType method but as far as I've seen none of the MediaType options will work for text/json.
Request req = new Request();
String url = "<url>";
HttpHeaders headers = new HttpHeaders();
headers.setContentType( MediaType.TEXT_JSON ); // this isn't valid but is where I have tried setting the content-type to text/json
HttpEntity< Request > entity = new HttpEntity<>( req, headers );
ResponseEntity< Response > resp =
restTemplate.exchange( url, HttpMethod.POST, entity, Response.class );
Request is the class that determines the servers response and Response is the Java representation of the returned json.
Ideally the returned json would be stored into the Response class but instead I am getting this error: InvocationTargetException: Failed to execute CommandLineRunner: Could not extract response: no suitable HttpMessageConverter found for response type [class Response] and content type [text/json]
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setSupportedMediaTypes(Arrays.asList(new MediaType("text","json")));
restTemplate.getMessageConverters().add(0, converter);
You need to add the converter to the rest template. Please refer Answer 1 or Answer 2.
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setSupportedMediaTypes(Arrays.asList(MediaType.TEXT_PLAIN, MediaType.APPLICATION_JSON));
restTemplate.getMessageConverters().add(0, converter);
I use Maven + Spring and I want use RestTemplate().postForEntity(url, request, responseType) + Content-Type=application/json
but I have this error:
org.springframework.web.client.RestClientException: Could not write request: no suitable HttpMessageConverter found for request type [com.kizeoforms.model.User] and content type [application/json]
java REST client code:
User user = new User();
user.setUser("foo");
user.setPassword("**********");
user.setCompany("xxxxxx");
MultiValueMap<String, String> headers = new LinkedMultiValueMap<String, String>();
headers.add("Content-Type", "application/json");
HttpEntity<User> request = new HttpEntity<User>(user, headers);
ResponseEntity<Object> response = new RestTemplate().postForEntity("https://www.kizeoforms.com:443/rest/v3/login", request, Object.class);
System.out.println(response.getStatusCode());
I had new MappingJackson2HttpMessageConverter() to restTemplate:
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
ResponseEntity<Object> response = restTemplate.postForEntity("https://www.kizeoforms.com:443/rest/v3/login", request, Object.class);
Look into the Restemplate constructor, if there are supported serialized packaged included in your project, the corresponding message converters will be added. So you can add a dependency package, such as com.google.gson.Gson or javax.json.bind.Jsonb, then you needn't handle the message converts explicitly.
I have Spring Rest service defined as below.
#RequestMapping(value = "/mobilebuild", method = RequestMethod.POST)
public StringWrapper buildApp(#RequestParam("projectName") String projectName, #RequestParam("appId") String projectId, #RequestParam("version") String version, #RequestParam("app") MultipartFile file) {
//Process to build app
return WMUtils.SUCCESS_RESPONSE;
}
From client side i am using rest template as follows
final List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
messageConverters.add(new ByteArrayHttpMessageConverter());
messageConverters.add(new StringHttpMessageConverter(Charset.forName(CommonConstants.UTF8)));
messageConverters.add(new ResourceHttpMessageConverter());
messageConverters.add(new SourceHttpMessageConverter<Source>());
messageConverters.add(new AllEncompassingFormHttpMessageConverter());
messageConverters.add(new FormHttpMessageConverter());
RestTemplate template = new RestTemplate(messageConverters);
MultiValueMap<String, Object> parts = new LinkedMultiValueMap<String, Object>();
//Post Parameters
parts.add("projectName", "FirstProject");
parts.add("appId", "app12345");
parts.add("version", "1.0");
// MultipartFile
parts.add("app", new FileSystemResource(tempFilesStorageManager.getFilePath("/tmp/app.zip")));
HttpHeaders headers = new HttpHeaders();
headers.add("Cookie", auth);
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
String url = "http://localhost:8080/AppManager/services/mobilebuild";
HttpEntity<MultiValueMap> requestEntity = new HttpEntity<MultiValueMap>(parts, headers);
ResponseEntity<String> responseEntity = template.postForEntity(endpointAddress, requestEntity, String.class);
String response = responseEntity.getBody();
I am unable to read the request parameters from controller (server): getting the following error
Error: request parameter projectName is not present in the request.
So please suggest me the way to achieve this.
According to javadoc of HttpEntity , the first parameter is request body and second one is request headers, but your client is sending request parameters inside request body and your controller is expecting them as #RequestParam, hence the error.
So either change your client to send the request parameters in the end point address URL to match your server side as ...projectName=FirstProject&appId= app12345&version=1.0....
Or encapsulate all your #RequestParam fields inside a single DTO class and add #RequestBody annotation on server side if your client wants to send in request body.
I need to send a POST HTTP request using Robospice for Android that will have data in the following format:
Content-Type: application/json
{'var1':'var1val','telNumber':'var2val'}
There may be other HTTP headers inside but this is the only header required by the server - I've tested it with a simple HelloWorld request that doesn't require any specific objects in the body.
The problem is that I can't send request body in the right format. I'm doing everything according the Robospice tutorial.
loadDataFromNetwork() method
public T loadDataFromNetwork() throws Exception { // I'm making generic requests, T is a class representing given request
Uri.Builder uriBuilder = Uri.parse(mUrl).buildUpon(); // mURL is just a full URL, including the method (just HTTP, not HTTPS)
MultiValueMap<String, String> body = new LinkedMultiValueMap<String, String>();
for (NameValuePair nvp : mPostParams) { // From the constructor: mPostParams = new ArrayList<NameValuePair>();
body.add(nvp.getName(), nvp.getValue());
}
HttpEntity<?> requestEntity = new HttpEntity<Object>(body, mHttpHeaders);
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<T> responseEntity = getRestTemplate().exchange(
uriBuilder.build().toString(), HttpMethod.POST, requestEntity,
mClazz);
return responseEntity.getBody();
}
createRestTemplate() in the JsonSpiceService class (which extends SpringAndroidSpiceService)
public RestTemplate createRestTemplate() {
RestTemplate restTemplate = new RestTemplate(true);
MappingJacksonHttpMessageConverter jsonConverter = new MappingJacksonHttpMessageConverter();
FormHttpMessageConverter formHttpMessageConverter = new
FormHttpMessageConverter();
StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
final List<HttpMessageConverter<?>> listHttpMessageConverters = restTemplate
.getMessageConverters();
setTimeout(restTemplate);
listHttpMessageConverters.add(jsonConverter);
listHttpMessageConverters.add(formHttpMessageConverter);
listHttpMessageConverters.add(stringHttpMessageConverter);
restTemplate.setMessageConverters(listHttpMessageConverters);
return restTemplate;
}
Doing it this way, I keep getting 500 Internal Server Error and I am pretty sure it is related to format of the body. Is there any way of getting a raw HTTP request (not the toString() version of some methods just a raw request)? What else can I be doing wrong - can it be about encoding of the body?
Note that I was testing the very same request with both Chrome app for sending REST requests and curl (worked fine).
You are getting confused in your SpringAndroid usage. Look at the docs of HttpEntity, you will see that you use a MultiValueMap as the Body. In that case, you are right, body.toString is called.
MultiValueMap is used in the way you think it is only for headers. For the body, HttpEntity expects a Pojo basically, and thus considers you MultiValueMap as a Pojo.
A simple workaround would be to create by hand the string you want to post as a body :
String body = "key=value&key=value&key=value"
This argument could be used as the first parameter of the constructor of HttpEntity.