Walmart (Java integration)- post feed with Resttemplate - java

I'm currently integrating Walmart into our application and I'm trying to post an Item Feed through the API method.
I've already succeeded in posting a feed from the ARC tool, so I already know how to model the post request for it, my only problem is that I'm having difficulties in using it in my code, while using the Resttemplate.
Below is the request (from ARC - Chrome) that succeeded to post my item (I can see them in my Walmart Seller console) and the Java code for it (trimmed the credentials for security reason):
Obs: The signature and the other fields used in the Java code for the requests are correctly generated, because I used them in my request from ARC as well, so there's no issue in the headers' values, but in how I'm trying to set the file in the body request, as far as I can tell:
And the code for generating the headers and sending the post request with Resttemplate:
..............................
headers = new HttpHeaders();
headers.set("WM_SVC.NAME", "Walmart Marketplace");
headers.set("WM_QOS.CORRELATION_ID", "123456abcdef");
headers.set("WM_SEC.TIMESTAMP", timestamp);
headers.set("WM_SEC.AUTH_SIGNATURE", signatureString);
headers.set("WM_CONSUMER.ID", "my-consumer-id-cut-for-security-reasons");
headers.set("WM_CONSUMER.CHANNEL.TYPE", "my-channel-type");
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
headers.setAccept(Arrays.asList(MediaType.APPLICATION_XML));
headers.set("Host", "https://marketplace.walmartapis.com");
..............................
File file = new File("C:\\walmartfeed.xml");
DiskFileItem fileItem = new DiskFileItem("file", "text/xml", false, file.getName(), (int) file.length(), file.getParentFile());
fileItem.getOutputStream();
MultipartFile multipartFile = new CommonsMultipartFile(fileItem);
MultiValueMap<String, Object> parts =
new LinkedMultiValueMap<String, Object>();
parts.add("file", new ByteArrayResource(multipartFile.getBytes()));
HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<>(parts, headers);
restTemplate.getMessageConverters().add(new FormHttpMessageConverter());
restTemplate.getMessageConverters().add(new ByteArrayHttpMessageConverter());
restTemplate.getMessageConverters().add(new MultipartAwareFormHttpMessageConverter());
ResponseEntity<FeedAcknowledgement> response = restTemplate.exchange("https://marketplace.walmartapis.com/v3/feeds?feedType=item", org.springframework.http.HttpMethod.POST, request, FeedAcknowledgement.class);
I am receiving a 400 status code saying it's a bad request.
Did you manage to post feeds for Walmart or is there any other way to use Resttemplate to post multipart/form-data / files ?
Thanks

Related

How to upload hosted file over the Rest Template?

I want to pass a hosted file over the rest template to another end point. I have to pass the hosted file URL as a String.
See the below code.
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
map.add(ATTACHMENT,new FileSystemResource(request.getAttachment()));
HttpEntity<MultiValueMap<String,Object>> outBoundRequest = new HttpEntity<>(map, headers);
return restTemplate.exchange(uri[0],HttpMethod.POST,outBoundRequest,Response.class);
Suppose I am passing "http://www.africau.edu/images/default/sample.pdf";
Why I am getting "Illegal char <:> at index 4: http:\www.africau.edu\images\default\sample.pdf"?
Can anyone help me out here.
Thanks,
Dasun.

Is it possible to use resttemplate to upload file in azure blob storage - Java

Is there a way to upload files to Azure blob storage using rest template in Java - Spring framework ? I see all examples using SDK and it was successful but we are told not to use SDK - Java.
I know question is 10,000 feet high, but any pointers/direction will help a lot.
No idea why not to use SDK, Also no idea who might be told you.
Anyway, Yes you can use RestTemplate or even better webClient.
All you have to do is to map the request sent with the SDK to the cloud.
You have to add header authentication manually. serialize the file I suppose.
And it's a lot of work when you do have a supported SDK for client.
For example , here is a simple request sent with WebClient for Redmine server
String url = "http://localhost:3001/projects.json"; //Redmine local server
RestTemplate restTemplate = new RestTemplate();
JSONObject object = new JSONObject(); //Json object that will need to be sent to redmine
object.put("name", "dummyName"); // Should look like this
object.put("identifier", "dummyId"); // {"project":{"identifier":"dummyId","name":"dummyName"}}
JSONObject body = new JSONObject();
body.put("project", object);
String plainCreds = "user:bitnami1"; // default basic auth encoding
byte[] plainCredsBytes = plainCreds.getBytes();
byte[] base64CredsBytes = Base64.encodeBase64(plainCredsBytes);
String base64Creds = new String(base64CredsBytes);
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "Basic " + base64Creds);
headers.add("Content-Type", "application/json");
RequestEntity<JSONObject> requestEntity = RequestEntity
.post(new URI(url))
.accept(MediaType.APPLICATION_JSON)
.headers(headers)
.body(body);
ResponseEntity<String> r = restTemplate.exchange(requestEntity, String.class);
And this is who the same example will look like using RestTemplate
String url = "http://localhost:3001/projects.json"; //Redmine local server
RestTemplate restTemplate = new RestTemplate();
JSONObject object = new JSONObject(); //Json object that will need to be sent to redmine
object.put("name", "dummyName"); // Should look like this
object.put("identifier", "dummyId"); // {"project":{"identifier":"dummyId","name":"dummyName"}}
JSONObject body = new JSONObject();
body.put("project", object);
String plainCreds = "user:bitnami1"; // default basic auth encoding
byte[] plainCredsBytes = plainCreds.getBytes();
byte[] base64CredsBytes = Base64.encodeBase64(plainCredsBytes);
String base64Creds = new String(base64CredsBytes);
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "Basic " + base64Creds);
headers.add("Content-Type", "application/json");
HttpEntity<Object> entity = new HttpEntity<Object>(body, headers);
ResponseEntity<String> result = restTemplate.exchange("http://localhost:3001/projects.json",
HttpMethod.POST,
entity,
String.class);
Both of these, Were only possible because am trying to match this curl request
curl --location --request POST 'localhost:3001/projects.json' \
--header 'Authorization: Basic dXNlcjpiaXRuYW1pMQ==' \
--header 'Content-Type: application/json' \
--data-raw '{"project":{"identifier":"dummyId","name":"dummyName"}}'
So once You know what the request looks like, You can use RestTemplate or WebClient, or any other similar class to build up your request.

Spring Calling External API with two files - multipart/form-data

I have an external API that I am invoking. The API takes two files as input. One File is .txt and other file is .JOSN.
I need to call this API through spring. This api is multipart/form-data.
public String doAPICall(String uri, String token) {
File idFile = new File ("c:\tmp\id_file.txt");
File jsonFile = new File ("c:\tmp\jsonFile.json");
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
body.add("idFile", new FileSystemResource(idFile));
body.add("jsonFile", new FileSystemResource(jsonFile));
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
headers.set("Authorization", "Bearer " + token);
HttpEntity<MultiValueMap<String, Object>> requestEntity= new HttpEntity<>(body, headers);
RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.exchange(
uri, HttpMethod.POST,requestEntity,
String.class).getBody().toString();
System.out.println(result);
return result;
}
Result: 500 - Internal Server Error. However, If I invoke the API with the same config via Insomnia/Postman, it works.
Also, it's not throwing 401 as the token is valid.
Do I need to set some extra header as I am uploading a txt and JSON file?
PS: I have typed the code here, the code might not be well-formatted.
Please share if anyone has any suggestions. Thank you!

Creating a Bitbucket-Repository in Java via REST

I am trying to create a Bitbucket repository using their REST-API. Everything seems to work except setting the "parent" project, where the repository needs to be created in. On this link a cURL example is provided. In the body, the parameter "scm" is set as either "git" or "hg", both being Strings, the parameter "project" seems to be a json object containing a key-value pair. Everything I tried so far did not work (json object, string, etc.)
Question: How can I create a repository IN a specific project?
My code looks the following:
RestTemplate restTemplate = new RestTemplate();
String url = "https://api.bitbucket.org/2.0/repositories/" + tName + "/" + rName;
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "Basic 1234567890qwert");
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
MultiValueMap<String, String> project = new LinkedMultiValueMap();
project.add("key", "aaaaaaaa"); //the repo should be created in the project aaaaaaaa
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
postParameters.add("scm", "hg"); //hg or git, does not matter
postParameters.add("project", project); //<-- the api ignores the declared project
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<MultiValueMap<String, Object>>(body, headers);
ResponseEntity<BitbucketRepository> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, BitbucketRepository.class);
System.out.println("createRepository: " + response);
return response;
You could use the bitbucket-rest library to do this like so:
BitbucketClient client = BitbucketClient.builder()
.endPoint("http://127.0.0.1:7990")
.credentials("admin:password") // will base64 for you if not already done. Can optionally use token auth as well.
.build();
CreateRepository crepo = CreateRepository.create("my-repo", true);
Repository repo = client.api().repositoryApi().create("my-project", crepo);

How to receive application/pdf response from a server using RestTemplate

I am trying capture the response of an HTTP request made by my java client code. The response has a content-type of application/pdf. In the logs I can see that the server sent a response in
Object result = getRestTemplate().postForObject(urlString, formDataHttpEntity, returnClassObject, parametersMapStringString);
and I get the following JUnit error:
org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type
[java.lang.Object] and content type [application/pdf]
What do I need to do to get past this? My ultimate goal is to take this in a byte[] and push it in a DB table field of blob type
Note: I get the following response header from the server
HTTP/1.1 200 OK Cache-Control: max-age=0,must-revalidate
Content-Disposition: attachment; filename="Executive Summary.PDF"
Content-Type: application/pdf
Thanks Thomas it worked.
I added ByteArrayHttpMessageConverter to the RestTemplate and it worked.
Code I added:
ByteArrayHttpMessageConverter byteArrayHttpMessageConverter = new ByteArrayHttpMessageConverter();
List<MediaType> supportedApplicationTypes = new ArrayList<>();
MediaType pdfApplication = new MediaType("application","pdf");
supportedApplicationTypes.add(pdfApplication);
byteArrayHttpMessageConverter.setSupportedMediaTypes(supportedApplicationTypes);
List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
messageConverters.add(byteArrayHttpMessageConverter);
restTemplate = new RestTemplate();
restTemplate.setMessageConverters(messageConverters);
Object result = getRestTemplate().getForObject(url, returnClass, parameters);
byte[] resultByteArr = (byte[])result;
API I calling to get PDF is returning InputStreamResource.
To get the response, I used it this way and I was able to get a successful byte array of pdf.
public byte[] callApiToGetPDF(Object reqData) {
String urlForEndPoint= baseUrl + "/" + "";
HttpEntity<Object> entity = new HttpEntity<>(reqData, buildHeaders());
return restTemplate.postForEntity(urlForEndPoint, entity, byte[].class).getBody();
}

Categories

Resources