Spring Rest Template to send JsonArray - spring

I am using spring rest template to send json array as request. Source code to send request is as follow:
JSONArray jsonArray = new JSONArray();
for (Iterator iterator = itemlist.iterator(); iterator.hasNext();) {
Item item = (Item)iterator.next();
JSONObject formDetailsJson = new JSONObject();
formDetailsJson.put("id", item.getItemConfId());
formDetailsJson.put("name", item.getItems().getItemName());
formDetailsJson.put("price", item.getPrice());
formDetailsJson.put("Cost",item.getCost());
jsonArray.put(formDetailsJson);
}
List<MediaType> acceptableMediaTypes = new ArrayList<MediaType>();
acceptableMediaTypes.add(MediaType.APPLICATION_JSON);
// Prepare header
HttpHeaders headers = new HttpHeaders();
headers.setAccept(acceptableMediaTypes);
// Pass the new person and header
HttpEntity<JSONArray> entity = new HttpEntity<JSONArray>(jsonArray, headers);
System.out.println("Json Object : "+entity);
// Send the request as POST
try {
ResponseEntity<String> result = restTemplate.exchange("my url", HttpMethod.POST, entity, String.class);
} catch (Exception e) {
logger.error(e);
return "Connection not avilable please try again";
}
And to accept request:
#RequestMapping(value = "/testStock", method = RequestMethod.POST,headers="Accept=application/xml, application/json")
public #ResponseBody int testStock(#RequestBody List<ItemList> jsonArray) {
logger.debug("Received request to connect ms access : "+jsonArray.size());
//int returnSizecount = stockList.getStocklst().size();
return 1;
}
The problem is that it giving me following error:
Could not write request: no suitable HttpMessageConverter found for request type [org.json.JSONArray].Any suggestion is greatly acceptable.

There are no MessageConverter for JSONArray, so I suggest do the following.
HttpEntity<JSONArray> entity = new HttpEntity<JSONArray>(jsonArray, headers);
Convert Class JSONArray to String, and add that to HttpEntity, you know use toString
java.lang.String toString()
Make a JSON text of this JSONArray.
HttpEntity entity = new HttpEntity(jsonArray.toString(), headers);
Or change to Jackson implementation Spring have support to that. XD
If you dont want to do the above, consider create your own implementation of messageConverter, that will work but is harder
update
HttpHeaders headers = new HttpHeaders();
headers.setAccept(acceptableMediaTypes);
headers.setContentType(MediaType.APPLICATION_JSON);
update 2 Change endpoint to.
#RequestMapping(value = "/testStock", method = RequestMethod.POST)
public #ResponseBody int testStock(#RequestBody String jsonArray) {

you need to have httpmessageconverter configured for your resttemplate, please read my post for configuring http message conveter for you webservice
http://stackoverflow.com/questions/19963127/new-to-spring-and-jackson-2-what-does-this-bean-declaration-allow-for-in-a-spri/19973636#19973636.
and for you problem to convert your http request to json you might add this entry in your restemplate configuration
<bean id="jsonMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>

The error is quite straightforward. You do not have a converter for the JSONArray. Converting the array to a String (using toString) did help you here, but there is a better way:
Just add a converter for the json.org objects:
Add this to your pom.xml
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-json-org</artifactId>
</dependency>
And then on your ObjectMapper add the JsonOrgModule:
mapper.registerModule(new JsonOrgModule());

Related

Sending a multipart request using RestTemplate

I want to make a multipart request to some external API (created using Spring Boot) but all I get is Required request part 'file' is not present.
I know the source code of the external API but I can't modify it. It looks like this:
#PostMapping("/upload")
public ResponseEntity handleFileUpload(#RequestParam("file") MultipartFile file){
return ResponseEntity.ok().build();
}
And from my application I create and send requests exactly like on the following snippet:
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
MultiValueMap<String, Object> body
= new LinkedMultiValueMap<>();
body.add("file", "dupa".getBytes());
HttpEntity<MultiValueMap<String, Object>> requestEntity
= new HttpEntity<>(body, headers);
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate
.postForEntity("http://api:8080/upload", requestEntity, String.class);
return response.getBody();
What's the reason it doesn't work? The above code rewritten using Apache HttpClient works like charm.
You basically have two options, the solution with byte array:
map.add("file", new ByteArrayResource(byteArrayContent) {
#Override
public String getFilename() {
return "yourFilename";
}
});
I remember having a problem with just adding a byte array, so you need to have a filename too and use ByteArrayResource.
Or adding a File:
map.add("file", new FileSystemResource(file));

spring boot rest client connection Exception:: org.springframework.web.client.HttpClientErrorException: 400 null

while i am executing below code i am getting error like
"org.springframework.web.client.HttpClientErrorException: 400 null".
but when i use postman to call this "http://localhost:2018/test" it is working.
static final String URL_EMPLOYEES = "http://localhost:2018/test";
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(new MediaType[] {
MediaType.APPLICATION_JSON}));
// Request to return XML format
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("replyMsg", "str");
// HttpEntity<Employee[]>: To get result as Employee[].
HttpEntity<String> entity = new HttpEntity<String>(headers);
// RestTemplate
RestTemplate restTemplate = new RestTemplate();
// Send request with GET method, and Headers.
ResponseEntity<String> response =
restTemplate.exchange(URL_EMPLOYEES,
HttpMethod.POST, entity,String.class);
HttpStatus statusCode = response.getStatusCode();
// Status Code: 200
if (statusCode == HttpStatus.OK) {
// Response Body Data
msg=response.getBody();
if (msg != null) {
System.out.println(msg);
}
}
//my clint controller class
#RestController
public class TextController {
#RequestMapping(value="/test",method = RequestMethod.POST)
public String myData2(#RequestBody String payload) {
return "done";
}
}
any suggetions?
If you're using Jackson as your JSON parser, you can simply declare your parameter with the type TextNode. This is the Jackson type representing JSON strings.
public String updateName(#PathVariable(MY_ID) String myId, #RequestBody TextNode name) {
You can then use its asText method to retrieve its text value.
Here you are setting headers Content-Type with type JSON and passing the body of type text/String.
headers.setContentType(MediaType.APPLICATION_JSON); //setting your Content type as JSON.
So, First you need to change this to
headers.setContentType(MediaType.TEXT_PLAIN); //setting your Content type as Pure Text String.
and add some code after this line
// HttpEntity<Employee[]>: To get result as Employee[].
HttpEntity<String> entity = new HttpEntity<String>(headers);
add this code
// HttpEntity<Employee[]>: To get result as Employee[].
HttpEntity<String> entity = new HttpEntity<String>(headers);
// RestTemplate
RestTemplate restTemplate = new RestTemplate();
// Send request with GET method, and Headers.
String entity_Str = new ObjectMapper().writeValueAsString(entity);
ResponseEntity<String> response =
restTemplate.exchange(URL_EMPLOYEES,
HttpMethod.POST, entity_Str, String.class);
This might work for you.. Thanks :)

How to send body content as raw JSON and not form-data in Spring Boot RestTemplate

I have a spring boot application and trying to invoke a rest service of another company by using RestTemplate.
The remote Rest Service required multiple header and body content as Raw JSON.
Here is the sample required body request :
{
"amount": "10000",
"destinationNumber": "365412"
}
But my request body generate like this :
{
amount= [10000],
destinationNumber= [365412]
}
I've done like this :
String BASE_URI = "http://server.com/sericeX";
RestTemplate template = new RestTemplate();
MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
headers.add("Authorization","Some token");
headers.add("Content-Type", "application/json");
MultiValueMap<String, String> bodyParam = new LinkedMultiValueMap<>();
bodyParam.add("amount", request.getAmount());
bodyParam.add("destinationNumber",request.getDestinationNumber());
HttpEntity entity = new HttpEntity(bodyParam,headers);
ResponseEntity<TransferEntity> responseEntity = template.exchange(BASE_URI, HttpMethod.POST, entity,TransferEntity.class);
TransferEntity transferEntity = responseEntity.getBody();
Could you please tell me how can i generate body request as JSON ?
Thanks to #Alex Salauyou based on his comment using HashMap instead of MultiValueMap solved the problem. Here is the changes need to be done:
HashMap<String, String> bodyParam = new HashMap<>();
bodyParam.put("amount", request.getAmount());
bodyParam.put("destinationNumber",request.getDestinationNumber());

RestTemplate gives 400 Bad Request Error on a Get Request

When I try to make a get request with Spring's RestTemplate, it gives 400 BAD Request. I can call the same url from javascript successfully with the headers below :
But the code below does not work. What might be the cause?
public Entity getEntityByUri(String uri) {
String req = "http://live.dbpedia.org/sparql?query=DESCRIBE%20%3Chttp://dbpedia.org/resource/Concept_learning%3E&format=application%2Fjson-ld";
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.ALL));
HttpEntity<String> httpEntity = new HttpEntity<String>(headers);
new RestTemplate().exchange(req, HttpMethod.GET, httpEntity, Map.class);
Entity entity = new Entity();
return entity;
}
Your url is already encoded. Popular browsers such as Chrome are capable of understanding and responding appropriately. However, it's not the same case with RestTemplate.
I had to decode your uri here and the decoded uri is DESCRIBE <http://dbpedia.org/resource/Concept_learning>
Having checked the browser console, I got to know you have two query strings passed in the url, they are query and format holding values DESCRIBE <http://dbpedia.org/resource/Concept_learning> and application/json-ld respectively.
I assume Entity class is the pojo class of json response.
Have created Entity as from your json response:
public class Entity {
private String value;
private String type;
// getters and setters omitted for brevity
}
Finally in your getEntityByUri method have got the instance of UriComponentsBuilder which handles uri encoding and query params.
To sum up, your getEntityByUri looks below.
public HttpEntity<Entity> getEntityByUri() {
String req = "http://live.dbpedia.org/sparql";
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(req)
.queryParam("query",
"DESCRIBE <http://dbpedia.org/resource/Concept_learning>")
.queryParam("format", "application/json-ld");
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.ALL));
HttpEntity<String> httpEntity = new HttpEntity<String>(headers);
return new RestTemplate().exchange(builder.build().encode().toUri(), HttpMethod.GET, httpEntity, Entity.class);
}
The above method didn't throw HTTP400 as the required query params have been passed in builder object.
Hope this helps and good luck!
Anyone getting same error make sure your URL is decoded means no percent symbols in url (if space in param values).
This worked for me
try {
requestURL = URLDecoder.decode("http://api.com?p=1&groups=3212&affected-since=2019-06-06T14%3A11%3A14.880&detail=full&after-id=43536", "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
Maybe
headers.setAccept(Arrays.asList(MediaType.ALL));
generates a malformed "Accept" header field? (FWIW, why do you send it at all???)

How to send GET request with headers by Spring

It will call another REST API with a GET request.
#RequestMapping(value = "xxxx/{id}", method = RequestMethod.GET)
public #ResponseBody GetObjet GET( #PathVariable("id") String id,
#RequestHeader(value="X-Auth-Token") String Token) {
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.add("X-Auth-Token", Token);
HttpEntity entity = new HttpEntity(headers);
ResponseEntity<GetObjet> response = restTemplate.exchange(url, HttpMethod.GET, entity, GetObjet.class);
return response.getBody();
}
Always 400 Error. It means that bad request or some errors in the request body. But this is GET so the resquest bodys is always empty. So this way to add header may be not right. Any ideas?
You can obtain the headers including the notation #RequestHeader in your method
public void displayHeaderInfo(#RequestHeader("Accept-Encoding") String encoding,
#RequestHeader("Keep-Alive") long keepAlive) {
}
o
You can read more about the request here
And the other way to abtain the URL is:
#RequestMapping(value = "/restURL")
public String serveRest(#RequestBody String body, #RequestHeader HttpHeaders headers){
//Use headers to get the information about all the request headers
long contentLength = headers.getContentLength();
...
StreamSource source = new StreamSource(new StringReader(body));
YourObject obj = (YourObject) jaxb2Mashaller.unmarshal(source);
...
}
Try using:
RestTemplate.getForEntity(url, GetObject.class);
You have some methods to request data from a rest API, such as getForEntity and getForObject, use the one you needed.

Resources