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