I have a code block like
final Invocation.Builder builder = webTarget.request();
final Entity<IFSRequestPresentation> entity = Entity.entity(ifsRequestPresentation, MediaType.APPLICATION_JSON);
final Response response = builder.post(entity);
The server (which is external to me and I can't see logs) is not returning me the data I expect. I believe that the json payload is not good
The IFSRequestPresentation is quite complex and I would like to see how it is represented as json String.
I am using Spring(4.0.3) and Jersey(2.8).
Is there a way I can log builder.post(entity) method? or at least see what entity looks like as json String?
I wrote it to file like
mapper.writeValue(new File("my.json"), IFSRequestPresentation);
as per Jackson documentation and got the json written to that file
Related
I am consuming a legacy rest service that receives xml text in the body but is sent as json as shown in the following image
Postman source request
I have done the process to transform the previous request to a request that receives a JSON in normal format
New JSON request
And then I transform it into the format that asks me for the source request, my problem is that I do not know how to send my string request because I get the following error when I try to send it
Request error new http request
I get the same error when I sent in my source request in plain text format
Plain text error legacy http request
however in code I already transformed this text into JSON format but probably incorrectly,in the following sample code the http entity is the xml string object required by the legacy service
#Value("${client.medExpInsuranceQuotation.uri}")
private String clientUri;
#Autowired
#Qualifier("restTemplategetPolicyWs")
private RestTemplate restTemplate;
#Override
public Object callMedicalExpenseInsuranceQuotation(MedicalExpenseInsuranceQuotationRequestClient requestClient) {
Gson gson = new Gson();
Object json = gson.toJson(requestClient.getXml(), String.class);
System.out.println("Object: "+json);
HttpEntity<Object> entity = new HttpEntity<>(json);
log.info(requestClient.getXml());
ResponseEntity<ResponseBean<Object>> responseEntity = restTemplate.exchange(clientUri, HttpMethod.POST, entity, new ParameterizedTypeReference<ResponseBean<Object>>() {
});
return responseEntity.getBody().getPayload();
}
Notes:
The legacy service only receives the body in the format indicated in image 1 (Postman source request)
if I try to send the body in traditional json format with an attribute identifier
attemp send normal json format
I get the following error without information
{
"Message": "An error has occurred."
}
I hope you can help me greetings
That rest service is consuming json format. Note the double quotes at the start and the end of the payload - this makes it json string. Not json object, or json array, but json string. You need to transform the xml payload into json string and send the correct content type header - application/json.
Edit: To get json string first you need the xml as a string(it's already a string, i know that sounds strange, but can't explain it better). Then you call toJson() on that xml. Something similar to this:
String xml = "<xml><tag></tag></xml>";
String jsonString = gson.toJson(xml);
System.out.println(jsonString);
I am trying to use the code below to send across a json string as a query param using Spring WebClient.
var client = WebClient.builder()
.baseUrl(baseurl)
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.build()
client.post().uri(uriBuilder -> uriBuilder.path("/api/SomeRequest")
.queryParam("response", responseJsonStr).build()
).retrieve().bodyToMono(ReponseObj.class).block()
I am seeing a error
java.lang.IllegalArgumentException: Not enough variables available to expand questionKey.
From the searching I have done, I can tell the issue is around the the Json String I am supplying as a query parameter(It has '{' and '}'). I think this might have to do with URI encoding. But looking at the details around encoding , I am not sure what the best way to approach this is.
NOTE: I can't make changes to the server that is expecting the Json string as a query param(it later decodes the json after extracting the query param).
Looks like you know that it's a really bad idea to send a json string as query param and not as post body, so I will not go into it any furhter.
You were right. You have to encode the query parameter on the client side to make it work. You can simply encode the param like this:
.queryParam("response", URLEncoder.encode(responseJsonStr, StandardCharsets.UTF_8))
Just make sure that you use the same character set as the server side.
I am sending the following Sig4 request:
Response response = new AmazonHttpClient(new ClientConfiguration())
.requestExecutionBuilder()
.executionContext(new ExecutionContext(true))
.request(request)
.errorResponseHandler(new AWSErrorResponseHandler(false))
.execute(new AWSResponseHandler(false));
I then convert the response to httpResponse: (not sure if its needed)
com.amazonaws.http.HttpResponse httpResponse = response.getHttpResponse();
My issue is that I was unable to find a simple explanation on how to extract the actual JSON response
string out of my response.
EDIT: Note that when I follow the SDK doc and try to extract the content as an input stream:
IOUtils.toString(response.getHttpResponse().getContent());
I get the following exception:
java.io.IOException: Attempted read from closed stream.
at org.apache.http.impl.io.ContentLengthInputStream.read(ContentLengthInputStream.java:165)
at org.apache.http.conn.EofSensorInputStream.read(EofSensorInputStream.java:135)
at com.amazonaws.internal.SdkFilterInputStream.read(SdkFilterInputStream.java:90)
at com.amazonaws.event.ProgressInputStream.read(ProgressInputStream.java:180)
at java.base/java.io.FilterInputStream.read(FilterInputStream.java:106)
at com.amazonaws.util.IOUtils.toByteArray(IOUtils.java:44)
at com.amazonaws.util.IOUtils.toString(IOUtils.java:58)
Any assistant would be highly appreciated :)
For HTTP responses I used RestAssured. With this it should work like this:
Response response = new AmazonHttpClient().execute() // build and run your query
String json = response.getBody().prettyPrint();
If you want to use the information of the json directly afterwards within the code I can recommend creating a POJO and then doing the following:
AmazonResponseDto dto = response.as(AmazonResponseDto.class)
A quick look up of the com.amazonaws.http.HttpResponse docs showed me, that you can get an InputStream from it, but not directly a json.
I don't know the package of the Response you used in your first code block, that's why I recommended RestAssured.
I found the reason for my issue. As some have suggested, the response is an input stream, yet when I tried to extract it to starting I either got a closed connection exception or nothing. To fix this I had to change .execute(new AWSResponseHandler(true)); to true instead of false in order to keep the connection open. AWSResponseHandler implements HttpResponseHandler and sets the following:
public AWSResponseHandler(boolean connectionLeftOpen) {
this.needsConnectionLeftOpen = connectionLeftOpen;
}
I hope this helps anyone who gets into a similar situation.
I'm currently using org.apache.http.entity.mime.MultipartEntityBuilder. The following don't work:
.addPart("key", new StringBody(jsonObject.toString()))
.addTextBody("key", jsonObject.toString())
.addTextBody("key", jsonObject.toString(), ContentType.APPLICATION_JSON)
Here, jsonObject is an org.json.JSONObject.
Non-nested fields and the image field validates correctly, but the nested fields don't seem to get filled out (the server returns "This field is required.").
Solutions that don't use the MultipartEntityBuilder are welcome as well.
I don't know anything about Apache's MultipartEntityBuilder.
But you could always send your image as a Base64 field in your json object. In the server, you'd need to map that to a byte[] field.
Multipart data does not play well with nested json. I settled for flattening the nested fields in the server API. Then, building the request still using MultipartEntityBuilder:
HttpEntity entity = MultipartEntityBuilder.create()
.addTextBody("inner_key1", jsonObject.get("inner_key1").toString())
.addTextBody("inner_key2", jsonObject.get("inner_key2").toString())
.addTextBody("inner_key3", jsonObject.get("inner_key3").toString())
.addBinaryBody("image", new File(imagePath))
.build();
I'm using google-http-java-client-1.10.3-beta for making RESTfull Json requests to a service provided by an external source.
I need to parse the Json that's coming in the response to build some POJOs to my app.
For that, I'm using HttpResonse method 'parse as':
response.parseAs(SomeModel.class)
But I'm getting this exception:
java.lang.IllegalArgumentException: No parser defined for Content-Type: application/json
at com.google.api.client.http.HttpResponse.parseAs(HttpResponse.java:497)
The responded json has this format:
[{"key" : {"key" : "value", "key" : "value"}}]
I had experminted some issues with other Json libraries when handling responses with square brackets, could that be the problem here?
Any ideas?
Responding to myself, the api needs you to set manually a JsonObjectParser object to the request involved.
A JsonObjectParser might be a GsonParser or JacksonParser or any other implented parser.
So, in order to set a GsonParser to your request you could use this code:
HttpRequest setJsonParser(HttpRequest request) {
JsonObjectParser parser = new JsonObjectParser(new GsonFactory());
return request.setParser(parser);
}
Then you will be able to do:
HttpRequest request = setJsonParser(request).execute().parseAs(SomeModel.class);
And all your POJOs will be automatically generated.
Note: I've upgraded my google-http-java-client version to 1.11.0-beta, an earlier version won't return a HttpRequest object when calling setParser so be carefull when using the presented code, you may need a void instead of a function.