java api REST client for POST ERROR: no suitable HttpMessageConverter - java

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.

Related

ERROR 400: Bad request: Error parsing form fields <EOL> when uploading image to Cloudflare Java

I have been trying to upload an image to Cloudflare images, but no matter what I try it gets rejected with "400 Bad Request: "ERROR 5400: Bad request: Error parsing form fields""
https://api.cloudflare.com/#cloudflare-images-upload-an-image-using-a-single-http-request
I am currently using SpringBoot with Rest Templates, here's an example of what I have tried so far:
public String uploadImage(File file) {
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new ByteArrayHttpMessageConverter());
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
headers.add(HttpHeaders.AUTHORIZATION, "Bearer " + API_TOKEN);
LinkedMultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
//body.add("\"file\"", new FileSystemResource(file));
body.add("file", new FileSystemResource(file));
HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<>(body, headers);
ResponseEntity<String> response = restTemplate.exchange(URL, HttpMethod.POST, request, String.class);
return response.toString();
}
I have tried using different forms of the file, changing the parameters, using different methods to make the request, ex: restTemplate.exchange vs restTemplate.getForObject, etc... and I have had no luck. If anyone can help me out or point me in the right direction, I would be greatly appreciated!

Trying to consume content-type [text/json] with Spring Boots's RestTemplate

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);

OAuth2RestTemplate.postForEntity RestClientException: No HttpMessageConverter for [org.x.xx] and content type [application/json]

I'm using OAuth2RestTemplate to query an external api that accept a JSON object.
HttpHeaders headers = new HttpHeaders();
headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
HttpEntity<XX> request = new HttpEntity<>(xX, headers);
ResponseEntity<String> response = oAuth2RestTemplate.postForEntity(url , request, String.class);
And I got this error :
org.springframework.web.client.RestClientException: No HttpMessageConverter for [com.yy.XX] and content type [application/json]
at org.springframework.web.client.RestTemplate$HttpEntityRequestCallback.doWithRequest(RestTemplate.java:956) ~[spring-web-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:732) ~[spring-web-5.1.4.RELEASE.jar:5.1.4.RELEASE]
I tried to add MappingJackson2HttpMessageConverter to my oAuth2RestTemplate but I got the same error.

How to change response http header in get request by spring RestTemplate?

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();

Unable to send POST parameters with mix of MultiPartFile to Rest Service using spring RestTemplate

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.

Categories

Resources