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();
}
Related
I have below API which returns back the access_token.
POST https://idcs-xxxxxxxxxbf08128c3d93a19c.identity.c9dev2.oc9qadev.com/oauth2/v1/token
in header content-type is application/x-www-form-urlencoded. also in body it contains below parameter.
I send user name and password and it is secured with basic authentication. It provides access_token when I call from postman. also it provides output when I consume using HttpUrlConnection
url = new URL(tokenURL);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.setRequestProperty("Authorization", auth);
connection.setRequestProperty("Accept", "application/json");
OutputStream os = connection.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os, "UTF-8");
osw.write("grant_type=client_credentials&scope=" + scope);
The above code is working properly. But when I use jersey it gives 415 error. I am using below code.
String user="idcs-oda-zzzxxxxxf93560b94eb8a2e2a4c9aac9a3ff-t0_APPID";
String password="xxxxxxx-6f71-4af2-b5cc-9110890d1456";
String scope = "https://idcs-oda-xxxxxxxxxxxxxxxxe2a4c9aac9a3ff-t0.data.digitalassistant.oci.oc-test.com/api/v1";
String tokenURL = "https://idcs-xxxxxxxxxxxxxxxx28c3d93a19c.identity.c9dev2.oc9qadev.com/oauth2/v1/token";
HttpAuthenticationFeature feature= HttpAuthenticationFeature
.basicBuilder()
.nonPreemptive()
.credentials(user,password)
.build();
ClientConfig clientConfig = new ClientConfig();
clientConfig.register(feature);
Client client = ClientBuilder.newClient(clientConfig);
WebTarget webTarget= client.target(tokenURL);
PostDetails post= new PostDetails("client_credentials",scope); //Bean class to assign body parameter
Response response= webTarget.request()
.header("Content-Type", "application/x-www-form-urlencoded")
.post(Entity.json(post));
System.out.println(response);
Can somebody tell me what mistake I am doing in Response line.
You need to set your Accept on the request method:
Response response= webTarget.request(MediaType.APPLICATION_JSON)
.header("Content-Type", "application/x-www-form-urlencoded")
.post(Entity.json(post));
You also need to ensure that if your API accepts application/x-www-form-urlencoded content, that is what you are sending.
Currently, you are sending application/json content based on your usage of Entity.json(post).
I don't know what type is assigned to post, but you need to figure out how to convert it either to a Form or a MultiValuedMap<String,String>, and then use the form method on Entity to submit your content.
Response response= webTarget.request(MediaType.APPLICATION_JSON)
.header("Content-Type", "application/x-www-form-urlencoded")
.post(Entity.form(postForm)); //assuming postForm typed as Form or MultiValuedMap<String,String>
Taking a guess regarding post, creating postForm as a MultiValuedMap<String,String> may be as simple as the following (which you would place prior to your request, of course).
MultiValuedMap<String,String> postForm = new MultiValuedHashMap<>();
postForm.add("client_credentials",scope);
What you need is:
Response response= webTarget.request()
.accept("application/json") // Accept field from header of request
.header("Content-Type", "application/x-www-form-urlencoded") //manually set content-tyoe
.post(Entity.entity(input, MediaType.TEXT_PLAIN)); // request body
The best way to see what is Jersey actually is sending is to register logger, and log network. For example:
clientConfig.register(
new LoggingFeature(
new Slf4jLogger(this.getClass().getName(), null)));
where Slf4jLogger is from org.apache.cxf:cxf-core.
Trying to send a POST request with form-data in Body in RestAssured, however not sure how should do it.
In Postman, it's fine.
I've tried things like:
public Response create() {
return super
.given()
.contentType("multipart/form-data")
.multiPart("MetaDataOne", new File("file.txt"))
.multiPart("MetaDataTwo", new File("file2.txt"))
.basePath("/create")
.log().all()
.post()
.then()
.log().all()
.extract()
.response();
}
But seems that my files are not being sent in the request.
Console log
Multiparts
Content-Disposition form-data; name = MetadataOne; filename = file
Content-Type: application/octet-stream
{"error": 415, "description": Content type application/octet-stream not supported}
Headers
Can you try with this, This should overwrite the Content-Type as multipart/form-data rather than application/octet-stream
given().contentType("multipart/form-data").multiPart("MetaDataOne", new File("file.txt"), "multipart/form-data")
.multiPart("MetaDataTwo", new File("file2.txt"), "multipart/form-data").basePath("/create").log().all()
.post().then().log().all().extract().response();
It's very simple to consume a RESTFull webservice Api, just follow these simple steps
Step 1: Create a Request Object pointing to the Service
RestAssured.baseURI ="https://myhost.com/xyz";
RequestSpecification request = RestAssured.given();
Step 2: Create a JSON object which contains all the form fields
JSONObject jsonObject = new JSONObject();
jsonObject.put("Form_Field_1", "Input Value 1");
jsonObject.put("Form_Field_2", "Input Value 2");
jsonObject.put("Form_Field_3", "Input Value 3");
jsonObject.put("Form_Field_4", "Input Value 4");
Step 3: Add JSON object in the request body and send the Request
request.header("Content-Type", "application/json");
request.body(jsonObject.toJSONString());
Post the request and check the response
Response response = request.post("/register");
Step 4: Validate the Response
int statusCode = response.getStatusCode();
Code:
RestTemplate template=new RestTemplate();
HttpHeaders headers=new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<?> httpEntity=new HttpEntity<>(body,headers);
ResponseEntity<String> postForEntity = template.postForEntity("url", httpEntity, String.class);
Json Response:
笀∀琀爀愀渀猀愀挀琀椀漀渀䤀䐀∀㨀∀娀㜀㌀㐀䔀㤀㈀㈀㘀㜀㈀㌀㔀㠀㘀㤀㔀∀Ⰰ∀猀琀愀琀甀猀∀㨀 Ⰰ∀爀攀焀吀猀∀㨀∀㈀ ㈀ ⴀ 㐀ⴀ㈀ ∀Ⰰ∀愀搀搀爀倀漀椀渀琀䰀椀猀琀∀㨀嬀笀∀爀攀焀䤀搀∀㨀∀娀㜀㌀㐀䔀㤀㈀㈀㘀㜀㈀㌀㔀㠀㘀㤀㔀∀Ⰰ∀爀攀猀椀䌀漀洀∀㨀∀唀∀Ⰰ∀愀搀搀爀倀渀琀吀欀渀∀㨀∀∀紀崀紀
by using this for loop I am able to get the correct json response:
for(int i=0; i< response.length(); i++) {
encoded += ((char) ((int)response.charAt(i) / 256 ));
}
Postman headers:
Request Headers:
Accept:Application/Json
Content-type:Application/Json
Response Headers:
Content-Type →application/json; charset=utf-8
Date →Thu, 04 Jun 2020 15:41:49 GMT
Server →Server Name
Transfer-Encoding →chunked
But I want to get the response without using this for loop.
In your code you are trying to receive the response in String format and here is the issue. First receive the response as Object, Once you receive the response as Object then try to convert it in String.
RestTemplate template=new RestTemplate();
HttpHeaders headers=new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<?> httpEntity=new HttpEntity<>(body,headers);
ResponseEntity<Object> postForEntity = template.postForEntity("url", httpEntity, Object.class);
Maybe you need to pass "Accept-Language" header.
It could be possible that postman sends default header value as "en-US"
The problem is the encoding. when sending your request make sure that you add the header
Content-type:Application/Json; charset=utf-8
And not just
Content-type:Application/Json
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
I am fetching the byte array using spring framework rest template,
But I also need to fetch the Mediatype of this byte .
The mediaType of this bytearray can be of any type.
The code used now for fetching byte is below.
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.valueOf("application/pdf")));
ResponseEntity<byte[]> result = restTemp.exchange(url, HttpMethod.GET, entity, byte[].class,documentId);
The above code will fetch only pdf content type.
How to set the contentType to accept any generic MediaType because the service at the other end is providing any random MediaType for the byteArray.
Could someone please suggest how the MediaType can be fetched.
Any suggestions are welcome..
Just not send the accept header to not force the server to return that content-type. This is the same as sending a wildcard */*
//HttpHeaders headers = new HttpHeaders();
//headers.setAccept(Collections.singletonList(MediaType.WILDCARD));
ResponseEntity<byte[]> result = restTemp.exchange(url, HttpMethod.GET, entity, byte[].class,documentId);
After this, extract the content-type from the headers of the response
byte body[] = result.getBody();
MediaType contentType = result.getHeaders().getContentType();
You can set the MediaType as application/octet-stream , look at here
You can store a media type in the HTTP headers and use - ResponseEntity.getHeaders(), for instance. or you can wrap byte array and media type into holder class.
MediaType mediaType = result.getHeaders().getContentType();