RestTemplate post for entity - spring

My post method gets called but my Profile is empty. What is wrong with this approach? Must I use #Requestbody to use the RestTemplate?
Profile profile = new Profile();
profile.setEmail(email);
String response = restTemplate.postForObject("http://localhost:8080/user/", profile, String.class);
#RequestMapping(value = "/", method = RequestMethod.POST)
public #ResponseBody
Object postUser(#Valid Profile profile, BindingResult bindingResult, HttpServletResponse response) {
//Profile is null
return profile;
}

You have to build the profile object this way
MultiValueMap<String, Object> parts = new LinkedMultiValueMap<String, Object>();
parts.add("email", email);
Object response = restTemplate.postForObject("http://localhost:8080/user/", parts, String.class);

MultiValueMap was good starting point for me but in my case it still posted empty object to #RestController my solution for entity creation and posting ended up looking like so:
HashedMap requestBody = new HashedMap();
requestBody.put("eventType", "testDeliveryEvent");
requestBody.put("sendType", "SINGLE");
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
// Jackson ObjectMapper to convert requestBody to JSON
String json = new ObjectMapper().writeValueAsString(request);
HttpEntity<String> entity = new HttpEntity<>(json, headers);
restTemplate.postForEntity("/generate", entity, String.class);

My current approach:
final Person person = Person.builder().name("antonio").build();
final ResponseEntity response = restTemplate.postForEntity(
new URL("http://localhost:" + port + "/person/aggregate").toString(),
person, Person.class);

Related

Okhttp create MultipartBody with spring MultipartFile and json object

I have a controller like so that accepts a MultipartFile and json object:
#PostMapping(value = "/v1/submit")
public ResponseEntity submit(
#RequestParam(value="myFile", required = true) MultipartFile myFile
, #Valid #RequestPart(value="fileMeta", required=true) FileMeta fileMeta
){
I need to forward this to a new url using an okhttpclient post with a Multipartbody containing both myFile and fileMeta objects:
OkHttpClient client = new OkHttpClient();
MultipartBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("myFile", myFile.getName(), okhttp3.RequestBody.create(file, MediaType.parse("pdf"))
.addFormDataPart("fileMeta", fileMeta)
.build();
I am getting following error:
Cannot resolve method 'create(org.springframework.web.multipart.MultipartFile, okhttp3.MediaType)'
The method definition of OkHttp's RequestBody create is the following: create(MediaType contentType, byte[] content). It expects the first the MediaType and second the payload (either as byte[], File or other formats).
So you first have to switch the order of the method arguments and second convert the MultipartFile from Spring to a proper format that the create() method accepts, e.g. byte[] or File:
OkHttpClient client = new OkHttpClient();
MultipartBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("myFile", myFile.getName(), RequestBody.create(MediaType.parse("pdf"), file)
.addFormDataPart("fileMeta", fileMeta)
.build();
There are already multiple solutions available on StackOverflow to convert MultipartFile to File: How to convert a multipart file to File?
UPDATE: Example for using RestTemplate
#RestController
public class FileSendingController {
#PostMapping("/files")
public void streamFile(#RequestParam("file") MultipartFile file) {
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
body.add("file", file);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);
RestTemplate restTemplate = new RestTemplate();
restTemplate.postForEntity("http://upload.to", requestEntity, String.class);
}
}

Provide generic class instead of a mapper class while executing an API using resttemplate

I'm trying to write an integration test for one of the API, but however it returns a XML object, where I don't have any corresponding class inorder to map. How can I do without any class?
Here is my code
HttpHeaders authHeaders = new HttpHeaders();
authHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
authHeaders.add("Authorization", "Bearer "+oAuthToken );
UriComponentsBuilder builder=UriComponentsBuilder.fromUriString(PES_END_POINT + PES_RESOURCE)
.queryParam("count", "100")
.queryParam("app-name", "bb")
HttpEntity entity = new HttpEntity(authHeaders);
Object response = restTemplate.exchange(builder.toUriString(), HttpMethod.POST, entity , Class<T> ); --> Here what generic class can I provide?
Any help would be greatly appreciated.
just use the ObjectMapper
ResponseEntity<String> response = restTemplate.exchange(builder.toUriString(), HttpMethod.POST, entity , String.class);
JavaType javaType = objectMapper.getTypeFactory().constructType(yourClass);
YourGenericClass<T> result = objectMapper.readValue(response.getBody(), javaType);

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

Passing RequestParam data to Spring RestController

I am using restTemplate.exchangemethod to invoke one service from another service.My request url does accept a request parameter.
url is of the formhttp://localhost:8035/sgapp/student/fetchDeptNo?sid
In the conttroller it is written as
#RestController
#RequestMapping(value="/sgapp/student")
public class SiController{
#GetMapping(value = "/fetchDeptNo",consumes = "application/x-www-form-urlencoded")
public ResponseEntity<String> getSid(#RequestParam(name = "sid")String sid){
String sid = myRepo.getSidCode(sid);
System.out.println("sid received from DB::"+sid);
return new ResponseEntity<String>(sid,HttpStatus.OK);
}
}
In the caller application I am invoking it as
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
HttpEntity<?> entity = new HttpEntity<>(headers);
Map paramMap = new HashMap<String, String>();
paramMap.put("sid", sidData);
HttpEntity<String> sidRespnse = restTemplate.exchange(
"http://localhost:8035/sgapp/student/fetchDeptNo", HttpMethod.GET, entity, String.class,
paramMap);
But I'm getting folllowing exception:
org.springframework.web.client.HttpClientErrorException: 400 null
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:94) ~[spring-web-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:79) ~[spring-web-5.0.6.RELEASE.jar:5.0.6.RELEASE]
Can anyone provide any suitable solution to this???
That particular exchange method is used to substitute variables into the path.
If you want to pass query parameters, use UriComponentsBuilder to create the URL with query params:
UriComponentsBuilder builder =
UriComponentsBuilder
.fromHttpUrl(rootUri)
.queryParam("sid", sidData);
Then you can use RestTemplate as follows:
restTemplate.exchange(
builder.toUriString(),
HttpMethod.GET,
entity,
String.class);

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