I didn't find any example how to solve my problem, so I want to ask you for help. I can't simply send POST request using RestTemplate object in JSON
Every time I get:
org.springframework.web.client.HttpClientErrorException: 415 Unsupported Media Type
I use RestTemplate in this way:
...
restTemplate = new RestTemplate();
List<HttpMessageConverter<?>> list = new ArrayList<HttpMessageConverter<?>>();
list.add(new MappingJacksonHttpMessageConverter());
restTemplate.setMessageConverters(list);
...
Payment payment= new Payment("Aa4bhs");
Payment res = restTemplate.postForObject("http://localhost:8080/aurest/rest/payment", payment, Payment.class);
What is my fault?
This technique worked for me:
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<String>(requestJson, headers);
ResponseEntity<String> response = restTemplate.put(url, entity);
I ran across this problem when attempting to debug a REST endpoint. Here is a basic example using Spring's RestTemplate class to make a POST request that I used. It took me quite a bit of a long time to piece together code from different places to get a working version.
RestTemplate restTemplate = new RestTemplate();
String url = "endpoint url";
String requestJson = "{\"queriedQuestion\":\"Is there pain in your hand?\"}";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<String>(requestJson,headers);
String answer = restTemplate.postForObject(url, entity, String.class);
System.out.println(answer);
The particular JSON parser my rest endpoint was using needed double quotes around field names so that's why I've escaped the double quotes in my requestJson String.
I've been using rest template with JSONObjects as follow:
// create request body
JSONObject request = new JSONObject();
request.put("username", name);
request.put("password", password);
// set headers
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<String>(request.toString(), headers);
// send request and parse result
ResponseEntity<String> loginResponse = restTemplate
.exchange(urlString, HttpMethod.POST, entity, String.class);
if (loginResponse.getStatusCode() == HttpStatus.OK) {
JSONObject userJson = new JSONObject(loginResponse.getBody());
} else if (loginResponse.getStatusCode() == HttpStatus.UNAUTHORIZED) {
// nono... bad credentials
}
As specified here I guess you need to add a messageConverter for MappingJacksonHttpMessageConverter
I'm doing in this way and it works .
HttpHeaders headers = createHttpHeaders(map);
public HttpHeaders createHttpHeaders(Map<String, String> map)
{
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
for (Entry<String, String> entry : map.entrySet()) {
headers.add(entry.getKey(),entry.getValue());
}
return headers;
}
// Pass headers here
String requestJson = "{ // Construct your JSON here }";
logger.info("Request JSON ="+requestJson);
HttpEntity<String> entity = new HttpEntity<String>(requestJson, headers);
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
logger.info("Result - status ("+ response.getStatusCode() + ") has body: " + response.hasBody());
logger.info("Response ="+response.getBody());
Hope this helps
If you are using Spring 3.0, an easy way to avoid the org.springframework.web.client.HttpClientErrorException: 415 Unsupported Media Type exception, is to include the jackson jar files in your classpath, and use mvc:annotation-driven config element. As specified here.
I was pulling my hair out trying to figure out why the mvc-ajax app worked without any special config for the MappingJacksonHttpMessageConverter. If you read the article I linked above closely:
Underneath the covers, Spring MVC
delegates to a HttpMessageConverter to
perform the serialization. In this
case, Spring MVC invokes a
MappingJacksonHttpMessageConverter
built on the Jackson JSON processor.
This implementation is enabled
automatically when you use the
mvc:annotation-driven configuration
element with Jackson present in your
classpath.
The "415 Unsupported Media Type" error is telling you that the server will not accept your POST request. Your request is absolutely fine, it's the server that's mis-configured.
MappingJacksonHttpMessageConverter will automatically set the request content-type header to application/json, and my guess is that your server is rejecting that. You haven't told us anything about your server setup, though, so I can't really advise you on that.
Why work harder than you have to? postForEntity accepts a simple Map object as input. The following works fine for me while writing tests for a given REST endpoint in Spring. I believe it's the simplest possible way of making a JSON POST request in Spring:
#Test
public void shouldLoginSuccessfully() {
// 'restTemplate' below has been #Autowired prior to this
Map map = new HashMap<String, String>();
map.put("username", "bob123");
map.put("password", "myP#ssw0rd");
ResponseEntity<Void> resp = restTemplate.postForEntity(
"http://localhost:8000/login",
map,
Void.class);
assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.OK);
}
I was getting this problem and I'm using Spring's RestTemplate on the client and Spring Web on the server. Both APIs have very poor error reporting, making them extremely difficult to develop with.
After many hours of trying all sorts of experiments I figured out that the issue was being caused by passing in a null reference for the POST body instead of the expected List. I presume that RestTemplate cannot determine the content-type from a null object, but doesn't complain about it. After adding the correct headers, I started getting a different server-side exception in Spring before entering my service method.
The fix was to pass in an empty List from the client instead of null. No headers are required since the default content-type is used for non-null objects.
This code is working for me;
RestTemplate restTemplate = new RestTemplate();
Payment payment = new Payment("Aa4bhs");
MultiValueMap<String, Object> map = new LinkedMultiValueMap<String, Object>();
map.add("payment", payment);
HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<MultiValueMap<String, Object>>(map, headerObject);
Payment res = restTemplate.postForObject(url, httpEntity, Payment.class);
If you dont want to process response
private RestTemplate restTemplate = new RestTemplate();
restTemplate.postForObject(serviceURL, request, Void.class);
If you need response to process
String result = restTemplate.postForObject(url, entity, String.class);
I tried as following in spring boot:
ParameterizedTypeReference<Map<String, Object>> typeRef = new ParameterizedTypeReference<Map<String, Object>>() {};
public Map<String, Object> processResponse(String urlendpoint)
{
try{
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
//reqobj
JSONObject request = new JSONObject();
request.put("username", name);
//Or Hashmap
Map<String, Object> reqbody = new HashMap<>();
reqbody.put("username",username);
Gson gson = new Gson();//mvn plugin to convert map to String
HttpEntity<String> entity = new HttpEntity<>( gson.toJson(reqbody), headers);
ResponseEntity<Map<String, Object>> response = resttemplate.exchange(urlendpoint, HttpMethod.POST, entity, typeRef);//example of post req with json as request payload
if(Integer.parseInt(response.getStatusCode().toString()) == HttpURLConnection.HTTP_OK)
{
Map<String, Object> responsedetails = response.getBody();
System.out.println(responsedetails);//whole json response as map object
return responsedetails;
}
} catch (Exception e) {
// TODO: handle exception
System.err.println(e);
}
return null;
}
For me error occurred with this setup:
AndroidAnnotations
Spring Android RestTemplate Module
and ...
GsonHttpMessageConverter
Android annotations has some problems with this converted to generate POST request without parameter. Simply parameter new Object() solved it for me.
If you don't want to map the JSON by yourself, you can do it as follows:
RestTemplate restTemplate = new RestTemplate();
restTemplate.setMessageConverters(Arrays.asList(new MappingJackson2HttpMessageConverter()));
ResponseEntity<String> result = restTemplate.postForEntity(uri, yourObject, String.class);
You can make request as a JSON object
JSONObject request = new JSONObject();
request.put("name","abc");
ResponseEntity<JSONObject> response =restTemplate.postForEntity(append_url,request,JSONObject.class); `enter code here`
Related
I am making a call to one of the Jasper server API endpoints and I have to set the header "Accept" to "application/json" for the service to return a JSON response. I have validated the API from Postman -
When I try to simulate the same behavior from my Spring Boot rest client, I try to set the accept header to 'application/json' but Spring seems to ignore the same and adds the accept header as shown below -
I have validated the same by enabling DEBUG for rest template using the following parameter -
logging.level.org.springframework.web.client.RestTemplate=DEBUG
Below is the code snippet for my rest client -
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setBasicAuth(serviceUsername, servicePassword, StandardCharsets.UTF_8);
ResponseEntity<String> response = null;
String url = serviceEndpoint + "?reportUnitURI="
+ URLEncoder.encode(reportPath, StandardCharsets.UTF_8.toString()).replaceAll("\\+", "%20")
+ "&label=" + URLEncoder.encode(label, StandardCharsets.UTF_8.toString()).replaceAll("\\+", "%20");
LOGGER.info("URL : " + url);
HttpEntity<String> requestEntity = new HttpEntity<String>("",
headers);
response = restTemplate.exchange(url, HttpMethod.GET, requestEntity, String.class);
Can someone please help explain the behavior here?
Why does my header values for 'accept' gets ignored?
What could be done to pass the 'accept' header properly?
Even though the code sets the accept header, the HttpMessageConverter used my scenario (StringHttpMessageConverter) does not allow changes on the accept headers and maintains the default values.
To get past that I have modified the StringHttpMessageConverter behavior at runtime to allow setting the preferred accept header.
#Bean
public RestTemplate getRestTemplate() {
final RestTemplate restTemplate = new RestTemplate();
final List<HttpMessageConverter<?>> converters = new ArrayList<>();
for (HttpMessageConverter converter : restTemplate.getMessageConverters()) {
if (converter instanceof StringHttpMessageConverter) {
((StringHttpMessageConverter) converter).setWriteAcceptCharset(true);
((StringHttpMessageConverter) converter).setSupportedMediaTypes(Collections.singletonList(MediaType.APPLICATION_JSON));
converters.add(converter);
}
}
restTemplate.setMessageConverters(converters);
return restTemplate;
}
Now, the framework allows my REST client to modify the header, code snippet below -
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
headers.setBasicAuth(serviceUsername, new String(new DecryptionService().decrypt(servicePassword)), StandardCharsets.UTF_8);
ResponseEntity<String> response = null;
try {
String url = serviceEndpoint + "?reportUnitURI=" + reportPath + "&label=" + processLabel(label, false);
HttpEntity<String> requestEntity = new HttpEntity<String>("",
headers);
response = restTemplate.exchange(url, HttpMethod.GET, requestEntity, String.class);
//more stuff
Please look at this simple code:
final String url = String.format("%s/api/shop", Global.webserviceUrl);
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
HttpHeaders headers = new HttpHeaders();
headers.set("X-TP-DeviceID", Global.deviceID);
HttpEntity entity = new HttpEntity(headers);
HttpEntity<Shop[]> response = restTemplate.exchange(url, HttpMethod.GET, entity, Shop[].class);
shops = response.getBody();
As you can see, above code is intended to GET list of shops from server (in json format) and map response to array of Shop objects.
Now I need to PUT new shop, for example as /api/shop/1. Request entity should have exactly the same format as returned one.
Should I add /1 to my url, create new Shop class object, with all fields filled with my values I want to put and then use exchange with HttpMethod.PUT?
Please, clarify it for me, I'm beginner with Spring. Code example would be appreciated.
[edit]
I'm double confused, because I just noticed also method RestTemplate.put(). So, which one should I use? Exchange or put()?
You could try something like :
final String url = String.format("%s/api/shop/{id}", Global.webserviceUrl);
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
HttpHeaders headers = new HttpHeaders();
headers.set("X-TP-DeviceID", Global.deviceID);
Shop shop= new Shop();
Map<String, String> param = new HashMap<String, String>();
param.put("id","10")
HttpEntity<Shop> requestEntity = new HttpEntity<Shop>(shop, headers);
HttpEntity<Shop[]> response = restTemplate.exchange(url, HttpMethod.PUT, requestEntity, Shop[].class, param);
shops = response.getBody();
the put returns void whereas exchange would get you a response, the best place to check would be documentation https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html
Hey all so i'm kind of frustrated as to why this isn't working and could use a helpful hand...new to RESTful operations. So far i'm running a web based app using Vaadin and Springboot. I'm trying to POST a set of variables to an external API. Below is the code:
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
HttpHeaders headers = new HttpHeaders();
String url = new String;
url = "a URL";
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
headers.add("Authorisation","oAuth Signature");
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
map.add("Name",name.toString());
map.add("Region",region.toString());
HttpEntity<MultiValueMap<String, String>> requestEntity= new
HttpEntity<MultiValueMap<String, String>>(map, headers);
ResponseEntity<String> response= restTemplate.postForEntity(url ,
HttpMethod.POST ,requestEntity, String.class);
HttpStatus status = response.getStatusCode();
String restCall = response.getBody();
i'm getting a problem with this line of code:
ResponseEntity response= restTemplate.postForEntity(url , HttpMethod.POST ,requestEntity, String.class);
It appears the problem is wit String.class and produces a: cannot resolve method error.
Exact error message:
Cannot resolve method 'postForEntity(java.lang.String, org.springframework.http.HttpMethod, org.springframework.http.HttpEntity>,java.lang.Class)'
I've removed the URL and oAuth signature for obvious reasons but i'd appreciate any helpful hints / tips anyone might have as to how to make this work?
I am trying to send some key-value pairs in Android Spring POST Request.It works correctly , if I am using a
MultiValueMap<String, String> map= new LinkedMultiValueMap<String, String>();
for that. Is there any way to avoid MultiValueMap & directly send the Class Object as Request.
One solution found is using Reflection , like the following
for (Field field:objAuth.getClass().getDeclaredFields()){
field.setAccessible(true);
map.add(field.getName(),field.get(objAuth)+"");
}
Code Snippet
RestTemplate restTemplate = new RestTemplate(true);
restTemplate.getMessageConverters().add(new FormHttpMessageConverter());
restTemplate.getMessageConverters().add(new MappingJacksonHttpMessageConverter());
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> map= new LinkedMultiValueMap<String, String>();
Authenticate objAuth = new Authenticate();
objAuth.setUserId("1");
objAuth.setType("Type");
objAuth.setoAuthToken("00112233");
objAuth.setResponseCode("9689");
objAuth.setResponseMessage("Last Message");
/**
* Using Reflection
*/
for (Field field:objAuth.getClass().getDeclaredFields()){
field.setAccessible(true);
map.add(field.getName(),field.get(objAuth)+"");
}
HttpEntity<?> requestEntity = new HttpEntity<Object>(map , requestHeaders);
String response = restTemplate.postForObject("http://posttestserver.com/post.php",requestEntity, String.class);
When posting a media type of APPLICATION_FORM_URLENCODED with FormHttpMessageConverter, you must use a MultiValueMap, as seen here. Alternatively, if you want to post JSON, Jackson is used internally to convert any object class to JSON output. Spring uses message converters to determine how to read/write objects, and which types are compatible with which media types.
I'm trying to retrieve some data from a REST service using spring for Android.
However I'm running into problems. I'm also using Robospice - and as such have a method like so:
public FunkyThingsList loadDataFromNetwork() throws Exception {
String baseURI =context.getResources().getString(R.string.baseWebServiceURI);
String uri = baseURI + "/FunkyThings/date/" + dateToLookUp.toString("yyyy-MM-dd");
RestTemplate restTemplate = getRestTemplate();
final HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
headers.setAccept( Arrays.asList(MediaType.APPLICATION_JSON));
HttpAuthentication authHeader = new HttpBasicAuthentication(username, password);
headers.setAuthorization(authHeader);
// Create the request body as a MultiValueMap
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
HttpMessageConverter<String> stringConverter = new StringHttpMessageConverter();
FormHttpMessageConverter formConverter = new FormHttpMessageConverter();
List<HttpMessageConverter<?>> msgConverters = restTemplate.getMessageConverters();
msgConverters.add(formConverter);
msgConverters.add(stringConverter);
restTemplate.setMessageConverters(msgConverters);
HttpEntity<?> httpEntity = new HttpEntity<Object>(map, headers);
final ResponseEntity<FunkyThingsList> responseEntity = restTemplate.exchange(url, HttpMethod.GET, httpEntity,FunkyThingsList.class);
return responseEntity.getBody();
}
Unfortunately this isn't working. I'm getting the following exception thrown:
org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [com.MyProject.DataClassPojos.RoboSpiceArrayLists.FunkyThingsList] and content type [application/json;charset=utf-8]
Now based on my Googling I get the feeling I need to add a message converter. I'm just not sure which message converter I need, or where I add it?
For the default JSON HttpMessageConverter, you'll need to add either Jackson 1 or Jackson 2 to your classpath.
Otherwise, you can add some other JSON library and write your own HttpMessageConverter which can do the deserialization. You add it to the RestTemplate. You can either use the constructor or this method.
If you are following the Spring for Android tutorial and you get the same error - this might be of help:
In your MainActivity.java:
...
RestTemplate restTemplate = new RestTemplate();
MappingJacksonHttpMessageConverter converter = new
MappingJacksonHttpMessageConverter();
converter.setSupportedMediaTypes(Collections.singletonList(MediaType.TEXT_HTML));
restTemplate.getMessageConverters().add(converter);
Use the converter in the call and configure it to use as a Media Type the TEXT_HTML, then use the instance of the converter.
Also the tutorial is a bit outdated so use the latest versions as suggested here in your build.gradle:
dependencies{
//Spring Framework for REST calls and Jackson for JSON processing
compile 'org.springframework.android:spring-android-rest-template:2.0.0.M3'
compile 'com.fasterxml.jackson.core:jackson-databind:2.4.1.3'
}
repositories {
maven {
url 'https://repo.spring.io/libs-milestone'
}
}