I have added Dependency for Gson in pom.xml
public ResponseEntity<String> findSearchInfo(#RequestParam String searchName)
{
ResponseEntity<String> response = gasRESTTemplate
.getForEntity(uri,String.class);
Gson gson = new Gson();
response = gson.toJson(response);
return response;
}
uri is returning me a HashMap which I want to convert to JSON.So I have used Gson's toJson method.Now the problem is that method is returning me json but i am unable to assign it to response cause it's type is ResponseEntity which is compulsory.
So what should I do to return that json by response?
Because of this I am getting error
required: org.springfremwork.http.ResponseEntity<java.lang.String>
found: java.lang.String
I know return type is ResponseEntity
So How should I initialize that JSON to response variable.
What about using this constructor (source) :
ResponseEntity(T body, MultiValueMap<String,String> headers, HttpStatus statusCode)
ResponseEntity<String> response =
new ResponseEntity(gson.toString(),
new MultiValueMap(),
HttpStatus.OK);
Related
I am dealing with an API that don't accept multi line json body and accept only 1 json line body (json compact form)
The below payload is valid because it's compact in just 1 line
And the below payload is not passing because it's multiline
I have the same problem in the Java/Spring code where I got this error while posting my object in restemplate.
Is there a way to convert the payload body into 1 single json line?
Code I am using to post the payload via RestTemplate
private HttpHeaders headers() {
HttpHeaders headers = new HttpHeaders();
headers.setAccept(List.of(MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN));
return headers;
}
post(ParameterizedTypeReference type, REQUEST myObject, URI uri) {
HttpEntity<REQUEST> entity = new HttpEntity<>(myObject, headers());
ResponseEntity<String> res = restTemplate.exchange(uri, HttpMethod.POST, entity , type);
}
The solution that worked for me is to annotate my request class with a custom JsonSerializer
This MyRequestClassSerializer#serialize will be called once restTemplate.exchange(uri, HttpMethod.POST, entity , type); is executed
Hence the payload will be compacted in 1 line by using JsonGenerator#writeRawValue
public class MyRequestClassSerializer extends JsonSerializer<MyRequestClass> {
#Override
public void serialize(MyRequestClass value, JsonGenerator jsonGenerator, SerializerProvider provider) throws IOException {
jsonGenerator.writeStartObject();
ObjectMapper mapper = ((ObjectMapper) jsonGenerator.getCodec());
jsonGenerator.writeFieldName("FieldName");
String stringValue = mapper.writeValueAsString(value);
jsonGenerator.writeRawValue(stringValue);
jsonGenerator.writeEndObject();
}
}
#JsonSerialize(using = MyRequestClassSerializer.class)
public class MyRequestClass{
...
}
I have a POJO of the form:
#Data
public class BaseRequest {
private String type;
private Map<String, Object> details;
private Map<String, Object> signature;
}
I have a service running which only accepts Content Type: "application/x-www-form-urlencoded".
I have written a client in Java which uses Spring's RestTemplate to make calls.
public String getInvoice(BaseRequest req, String url) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
HttpEntity<BaseRequest> httpEntity = new HttpEntity<BaseRequest>(req, headers);
String response = this.restTemplate.postForObject(url, httpEntity, String.class);
return response;
}
However, it throws an error:
org.springframework.web.client.RestClientException: Could not write request: no suitable HttpMessageConverter found for request type [com.x.y.z.BaseRequest] and content type [application/x-www-form-urlencoded]
It works if I set the content type as JSON:
headers.setContentType(MediaType.APPLICATION_JSON);
I know it works for JSON because I have configured my RestTemplate Bean with JacksonHTTPMessageConverter. So I can easily convert POJOs to application/json. However, I am not able to figure out how to do that with application/x-www-form-urlencoded.
I've been searching this for awhile now, and the only solution which I've found is to write my own converter to convert my BaseRequest class to Spring's MultiValueMap, and then Spring's FormHttpMessageConverter will automatically handle it. But I want to avoid doing that. Is there any other way around this?
Any leads would be appreciated. Thanks!
EDIT:
My question is different from #JsonProperty not working for Content-Type : application/x-www-form-urlencoded. The conversion happening there is about accepting data in application/x-www-form-urlencoded and converting it to a POJO. My question is about converting a POJO to application/x-www-form-urlencoded while using Spring's resttemplate to make calls. And like I mentioned, I know I can achieve this by writing my own converter to convert my POJO to Spring's MultiValueMap. However, I want to know if I can avoid doing this.
EDIT:
Dump of $_POST on the API when I send my data as MultiValueMap<String, Object>:
"array(0) {
}"
Dump of $_POST on the API when I send my data through Postman in the correct format:
"array(2) {
["type"]=>
string(16) "abcd"
["details"]=>
array(1) {
["template_file"]=>
string(16) "x.html"
}
}"
Try to convert your nested object in request payload to the org.springframework.util.MultiValueMap. Add and implement converter method in your POJO
public class BaseRequest {
// ...
public MultiValueMap<String, Object> toMap() {
MultiValueMap<String, Object> result = new LinkedMultiValueMap<>();
result.add("type", type);
result.put("details", details);
result.put("signature", signature);
return result;
}
}
Now use it during request creation
HttpEntity<BaseRequest> httpEntity = new HttpEntity<BaseRequest>(req.toMap(), headers);
That is caused because inside FormHttpMessageConverter which performs actual conversion method canRead(Class<?>, MediaType) checks if MultiValueMap.class.isAssignableFrom(clazz) where clazz is your payload object. In your case it failed, so FormHttpMessageConverter skipped.
Hope it helps!
I will like to use the JSON response inside a controller. I am calling a method that returns the JSON. See my code below. Please how do I loop through the Json object returned inside my controller. I need to use the properties like sending mail to the email addresses from another method inside my controller .
My method that does that returns the JSON :
#ResponseBody
private ResponseEntity<?> queryIsw(String ref, String amt) throws Exception{
String pdtid = "62";
String salt = "D3D1D05AFE42AD50818167EAC73C109168A0F108";
RestTemplate restt = new RestTemplate();
String uri = "https://bestng.com/gettransaction.json";
MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
params.add("productid", pdtid);
params.add("transactionreference", ref);
params.add("amount", amt);
UriComponents uriComponents = UriComponentsBuilder.fromHttpUrl(uri).queryParams(params).build();
URI oro = uriComponents.toUri();
HttpHeaders hea = new HttpHeaders();
String hs = pasher(pdtid, ref, salt);
hea.add("hash", hs);
HttpEntity<String> hent = new HttpEntity<String>(hea);
ResponseEntity<Object> resp = restt.exchange(oro, HttpMethod.GET, hent, Object.class);
return resp;
}
Below is my call to this method above from another method :
ResponseEntity<?> dres = queryIsw(dref,ama);
Kindly explain how I can use properties of 'dres' returned in my controller .
Thanks
Try taking a look at the Jackson JSON to Java mapping tools and specifically the ObjectMapper. It can convert a properly formatted JSON string into an object hierarchy from which you can pull out the data that you need. Jackson is a frequently used tool for this activity. Take a look at the tutorial for more details:
http://www.mkyong.com/java/how-to-convert-java-object-to-from-json-jackson/
If you need more help, do ask.
I am assuming that it will return within the body of the ResponseEntity.
Try:
String body = dres.getBody();
You can use something that can parse that string to a json object. Something like:
JSONObject jObject = new JSONObject(body);
See:
http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/http/ResponseEntity.html
Java String to JSON conversion
I have a REST API with this endpoint:
#GET
#Path("rol/{codEmp}")
#Produces(MediaType.TEXT_PLAIN)
public String getRole(#PathParam("codEmp") Long codEmp) {
return dao.getRole(codEmp);
}
An example of response can be: HOUSEKEEPER.
I consume it this way:
#Override
public String getRole(Long codEmp) {
HashMap<String, Object> urlVariables = new HashMap<String, Object>();
urlVariables.put("codEmp", codEmp);
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setAccept(Collections.singletonList(MediaType.parseMediaType("text/plain")));
HttpEntity<Object> requestEntity = new HttpEntity<Object>(httpHeaders);
return restTemplate.exchange(rootUrl.concat("/rol/{codEmp}"), HttpMethod.GET, requestEntity, String.class, urlVariables).getBody();
}
But I get this error:
"Could not extract response: no suitable HttpMessageConverter found
for response type [java.lang.String] and content type [text/plain]"
I know the right way is to send a JSON response but I have to do it with raw String.
How can I solve it?
Thanks
Solved. I have added an String converter to my Rest Template:
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
I struggled with an extrange spring behavior using RestTemplate (org.springframework.web.client.RestTemplate) without success.
I use in my hole application below code and always receive an XML response, which I parse and evaluate its result.
String apiResponse = getRestTemplate().postForObject(url, body, String.class);
But can't figure out why a server response is in JSON format after executing:
String apiResponse = getRestTemplate().getForObject(url, String.class);
I've debugged at low level RestTemplate and the content type is XML, but have no idea why the result is in JSON.
When I access from a browser the response is also in XML, but in apiResponse I got JSON.
I tried many options after reading Spring documentation
http://docs.spring.io/spring/docs/3.0.x/api/org/springframework/web/client/RestTemplate.html
Also tried to modify explicitly the headers but still can't figure it out.
I debugged RestTemplate class and noticed that this method is always setting application/json:
public void doWithRequest(ClientHttpRequest request) throws IOException {
if (responseType != null) {
List<MediaType> allSupportedMediaTypes = new ArrayList<MediaType>();
for (HttpMessageConverter<?> messageConverter : getMessageConverters()) {
if (messageConverter.canRead(responseType, null)) {
List<MediaType> supportedMediaTypes = messageConverter.getSupportedMediaTypes();
for (MediaType supportedMediaType : supportedMediaTypes) {
if (supportedMediaType.getCharSet() != null) {
supportedMediaType =
new MediaType(supportedMediaType.getType(), supportedMediaType.getSubtype());
}
allSupportedMediaTypes.add(supportedMediaType);
}
}
}
if (!allSupportedMediaTypes.isEmpty()) {
MediaType.sortBySpecificity(allSupportedMediaTypes);
if (logger.isDebugEnabled()) {
logger.debug("Setting request Accept header to " + allSupportedMediaTypes);
}
request.getHeaders().setAccept(allSupportedMediaTypes);
}
}
}
Could you give an idea?
I could solve my issue with RC.'s help. I'll post the answer to help other people.
The problem was that Accept header is automatically set to APPLICATION/JSON so I had to change the way to invoke the service in order to provide the Accept header I want.
I changed this:
String response = getRestTemplate().getForObject(url, String.class);
To this in order to make the application work:
// Set XML content type explicitly to force response in XML (If not spring gets response in JSON)
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_XML));
HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
ResponseEntity<String> response = getRestTemplate().exchange(url, HttpMethod.GET, entity, String.class);
String responseBody = response.getBody();