How to call MultipartFile Spring REST URL with RestTemplate - java

When I try to call following MultipartFile Spring REST url with my Spring Template base Test method, I got following exception. How can I make this correct. Thanks.
Spring REST URL:
#RequestMapping(value = "/media/uploadMultipartFile/{token}/{title}/{trailId}/{wpId}", method = RequestMethod.POST)
public #ResponseBody MediaHttp uploadMultipartFile(#RequestParam MultipartFile file,
#PathVariable String token,
#PathVariable String title,
#PathVariable String trailId,
#PathVariable String wpId,
HttpServletResponse response)
Test method:
try {
// Message Converters
List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>();
messageConverters.add(new FormHttpMessageConverter());
messageConverters.add(new SourceHttpMessageConverter<Source>());
messageConverters.add(new StringHttpMessageConverter());
messageConverters.add(new MappingJacksonHttpMessageConverter());
// RestTemplate
RestTemplate template = new RestTemplate();
template.setMessageConverters(messageConverters);
// URL Parameters
MultiValueMap<String, Object> parts = new LinkedMultiValueMap<String, Object>();
parts.add("token", "nkc2jvbrbc");
parts.add("title", "test mp4 file");
parts.add("trailId", "2");
parts.add("wpId", "7");
parts.add("file", new FileSystemResource("C:\\Users\\Public\\Pictures\\Sample Pictures\\test.mp4"));
// Post
MediaHttp result = template.postForObject(Constants.APPLICATION_URL + "/media/uploadMultipartFile/{token}/{title}/{trailId}/{wpId}", parts, MediaHttp.class);
} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
}
Exception:
Invalid amount of variables values in [http://test.com:8080/DMW-skeleton-1.0/media/uploadMultipartFile/{token}/{title}/{trailId}/{wpId}]: expected 4; got 0

The message is pretty clear, you don't specify any path parameters for submission. You only provide a map which will be send as the body of the request.
change your call to include those parameters as the last part of the method call.
// URL Parameters
MultiValueMap<String, Object> parts = new LinkedMultiValueMap<String, Object>();
parts.add("file", new FileSystemResource("C:\\Users\\Public\\Pictures\\Sample Pictures\\test.mp4"));
// Post
MediaHttp result = template.postForObject(Constants.APPLICATION_URL + "/media/uploadMultipartFile/{token}/{title}/{trailId}/{wpId}", parts, MediaHttp.class, "nkc2jvbrbc", "test mp4 file", "2", "7);

Related

Spring boot - restTemplate.postForObject - params are null

I have 2 spring boot apps running one as a frontend and another as a backend service. From the frontend i make an api call to the backend service and both the parameters that i send show up as null. I think the problem is in the rest template.
UPDATE
So i have noticed if i omit the content value then it works. Since content is the content of a file that is larger than 1mb I added the following to application.yml:
spring.servlet.multipart.max-file-size: 10MB
spring.servlet.multipart.max-request-size: 10MB
Here is my code which I updated from one posted in this issue:
How to POST form data with Spring RestTemplate?
But i still don't get the value in the backend controller instead both values are null.
public void upload(byte[] content, String name) {
String encodedString = Base64.getEncoder().encodeToString(content);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
map.add("fileName", name);
map.add("content", encodedString);
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(map, headers);
ResponseEntity<String> response = restTemplate.postForEntity(backendUrl + "/upload", request, String.class);
log.debug("Response from upload: " + response);
}
And here is the controller in the backend. Both fileName and content are null:
#CrossOrigin
#SneakyThrows
#ResponseBody
#PostMapping(value = "/upload")
public ResponseEntity<String> upload(#ModelAttribute FormModel form) {
byte[] decodedBytes = Base64.getDecoder().decode(form.getContent());
uploadService.upload(decodedBytes, form.getFileName());
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.set("Content-Type", "application/json");
return ResponseEntity.ok().headers(responseHeaders).body("Uploaded");
}
Can anyone please see what is wrong with this code?
Thanks in advance.
I guess the problem is that you are trying to use restTemplate.postForObject but with #RequestParam and not a #RequestBody.
In #RequestParam you are expecting the data to be received in the query params /upload?fileName=&content=. But you are actually sending it in the body with the restTemplate.postForObject(backendService+ "/upload", map, String.class);.
So my suggestion is to change
public ResponseEntity<String> upload(#RequestParam(value = "fileName") String fileName, #RequestParam(value = "content") String content)
to
public ResponseEntity<String> upload(#RequestBody Map<String, String> body)
and then get fileName and fileContent from the body.
Ok i could fix it by sending and receiving bytes instead of bytes encoded as string.
So in the resttemplate:
public void upload(byte[] bytes, String name) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
MultiValueMap<String, Object> map = new LinkedMultiValueMap<String, Object>();
map.add("fileName", name);
map.add("bytes", bytes);
HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<MultiValueMap<String, Object>>(map, headers);
log.debug("map values: " + map.toString());
ResponseEntity<String> response = restTemplate.postForEntity(backendUrl + "/upload", request, String.class);
log.debug("Response from upload: " + response);
}
And in the controller:
public ResponseEntity<String> upload(#ModelAttribute FormModel form) {
byte[] bytes = form.getBytes();
uploadService.upload(bytes, form.getFileName());
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.set("Content-Type", "application/json");
return ResponseEntity.ok().headers(responseHeaders).body("Uploaded");
}
Still it would be good to know why the previous version didn't work.

How can i return a Response from restTemplate put api?

i'm trying to retrieve an put api exposed response as a Response object
the valid url http://localhost:8081/nameoftheapplication*/{id}/validateToExportFile
the return format example when i tested it is like :
i'm using restTemplate exchange because the put just do the update,the method works fine when i change the return type to String but i want to return a Response for other treatment the method that i'm using actually is
public Response validateToExportFileExchange(ReturnValidationDetails returnValidationDetails) {
String validationURL = (validateToExportURI + "/" + returnValidationDetails.getReturnId() + "/validateToExportFile");
HttpHeaders headers = new HttpHeaders();
headers.add("Accept", "*/*");
List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>();
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setSupportedMediaTypes(Collections.singletonList(MediaType.APPLICATION_JSON_UTF8));
messageConverters.add(converter);
resttemplate.setMessageConverters(messageConverters);
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
HttpEntity<ReturnValidationDetails> validateToExportFileExchangeEntity = new HttpEntity<>(returnValidationDetails, headers);
return resttemplate.exchange(validationURL, HttpMethod.PUT, validateToExportFileExchangeEntity,
Response.class).getBody();
}
and i have this Exception :
Could not extract response: no suitable HttpMessageConverter found for response type [interface javax.xml.ws.Response] and content type [application/vnd.openxmlformats-officedocument.spreadsheetml.sheet]
thx in advance for your help

Testing Camel REST DSL

I am trying to test a Camel route. The route uses the REST DSL to receive POST requests, conduct some processing, and return a value.
My tests are returning odd messages bodies and I'm not sure why.
Here is the test:
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class ApplicationTest {
#Autowired
private TestRestTemplate restTemplate;
#Autowired
private CamelContext camelContext;
#Test
public void newRequest() throws IOException {
// Then call the REST API
// Read file as a string into a variable 'content'
String content = new String(Files.readAllBytes(Paths.get("test_data.csv")), StandardCharsets.UTF_8);
// Create a rest template to create a (post) request
RestTemplate restTemplate = new RestTemplate();
// Create Mulipart-form data and set the content type to multpart-form data
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
// Create an object called 'body' of type multipart
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
// Set content (of loaded file) into the multipart object
body.add("file", content);
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);
String serverUrl = "http://localhost:8081/";
ResponseEntity<String> response = restTemplate.postForEntity(serverUrl, requestEntity, String.class);
The response entity body value is with response status code 200:
{
"--_Q_XsVubda334izooe8NkhJMiv11hjg3kHE": "--_Q_XsVubda334izooe8NkhJMiv11hjg3kHE--"
}
I am expecting a JSON with legible key value pairs.
I would appreciate some tips on why I'm getting this response and if i've gone wrong anywhere in my test.

how to do post request with raw data via spring rest template

Can some one tell me how to send a POST request with raw data parameters as in the picture below
i have tried the following code but its not working
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
JsonObject properties = new JsonObject();
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
try {
properties.addProperty("app_id", appId);
properties.addProperty("identity","TestAPI");
properties.addProperty("event", "TestCompleted");
properties.addProperty("testType", t.getTestType());
properties.addProperty("testName",t.getTestName());
properties.addProperty("chapter","");
properties.addProperty("module","");
properties.addProperty("pattern",t.getTestPattern());
HttpEntity<String> request = new HttpEntity<>(
properties.toString(), headers);
// params.add("properties", properties.toString());
restTemplate.postForObject(url, request, String.class);
can someone help?
Try this :
#RestController
public class SampleController {
#RequestMapping("/req")
public String performReqest(){
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
JsonObject properties = new JsonObject();
properties.addProperty("no", "123");
properties.addProperty("name", "stackoverflow");
HttpEntity<String> request = new HttpEntity<>(properties.toString(), headers);
RestTemplate restTemplate = new RestTemplate();
String response = restTemplate.postForObject("http://localhost:4040/student", request, String.class);
return "Response from Server is : "+response;
}
#RequestMapping("/student")
public String consumeStudent(#RequestBody Student student){
System.out.println(student);
return "Hello.."+student.name;
}
}
class Student{
public int no;
public String name;
public Map<String,String> properties;
}
Don't forgot to move Student class and change all field to private with require getters and setters.
Above code is only for demo purpose.
Please try with this:
ResponseEntity<String> result = restTemplate.exchange(url, HttpMethod.POST, request, String.class);
Did u tried using postmaster and checked the output first. If its working then you can go for post or exchange method. exchange returns and post dont.
try this:
URI uri = new URI("something");
Map<String, Object> params = new HashMap<>();
params.put("app_id", "something");
params.put("identity", something);
HttpEntity<Map<String, String>> request = new HttpEntity(params , headers);
ResponseEntity<String> response = restTemplate.postForEntity(uri, request, String.class);

How to pass raw XML into RESTTemplate POST or PUT method without converting it?

I am trying to update or create xml file if not present. Then I use code below to send the file using PUT method of a service.
public void importClusterProperties(RestManPropertyHolder propertyHolder,File file,String id) throws RestManServiceException {
testRestTemplate = new TestRestTemplate(propertyHolder.getSbusUserName(), propertyHolder.getSbusUserPassword());
String sbusUrl = utils.prepareGatewayURI(propertyHolder);
try {
HttpHeaders requestHeaders = new HttpHeaders();
List <MediaType> mediaTypeList = new ArrayList<MediaType>();
mediaTypeList.add(MediaType.APPLICATION_ATOM_XML);
requestHeaders.setAccept(mediaTypeList);
requestHeaders.setContentType(MediaType.APPLICATION_ATOM_XML);
HttpEntity<String> requestEntity = new HttpEntity<String>(requestHeaders);
// Create the HTTP PUT request,
ResponseEntity<String> response = testRestTemplate.exchange(sbusUrl + "/clusterproperty?",HttpMethod.PUT, requestEntity,String.class);
if (null != response) {
System.out.println("RESPONSE::" + response.toString());
}
} catch (RestClientException rce) {
System.out.println("REST EXCEPTION:::" + rce.getMessage());
}
}
How to pass raw xml file into RestTemplate without converting it first into a java object?
enter image description here
Convert file to byte array and send it using ByteArrayHttpMessageConverter.
RestTemplate restTemplate = new RestTemplate();
// Add ByteArrayHttpMessageConverter if not present by default.
restTemplate.getMessageConverters().add(
new ByteArrayHttpMessageConverter());
String fileName = "path + file name";
// FileUtils is from Apache Commons IO
// import org.apache.commons.io.FileUtils;
byte[] requestBody = FileUtils.readFileToByteArray(new File(fileName));
HttpEntity<byte[]> requestEntity = new HttpEntity<byte[]>(requestBody , requestHeaders);
// Create the HTTP PUT request,
ResponseEntity<byte[]> response =
restTemplate.exchange("URL ...." , HttpMethod.PUT ,
requestEntity , byte[].class);

Categories

Resources