ResponseBody inconsistent JSON string (OKHttp 3.10.0) - java

Firstly I searched about this issue but couldn't find any solution.
I am sending a POST request to a web service. This web service returns response but I see that the response is not complete.
With PostMan I get full response without issue. But OKHttp cuts the response.
public List<Product> getProducts(String token, long bill_acct_id, long customer_id, Context context) {
if(token != null && !token.equals("")) {
Gson gson = new Gson();
List<Product> prods;
Map<String, String> list_of_headers = new HashMap<>();
list_of_headers.put("WSC-AUTH-TOKEN", token);
list_of_headers.put("Accept", "application/json, text/plain, */*");
list_of_headers.put("Content-Type", "application/json");
Headers headers = Headers.of(list_of_headers);
try {
Response response = RequestSender.post2("URL", "{\"billingAccountId\":\""+bill_acct_id+"\", \"customerId\":\""+customer_id+"\"}", headers, context);
int returnCode = response.code();
ResponseBody body = response.body();
Log.e("INFO", body.string());
if (returnCode == 200) {
prods = gson.fromJson(body.string(), new TypeToken<List<Product>>() {
}.getType());
return prods;
}
} catch (Exception ex) {
Log.e("Error", ex.getMessage());
ex.printStackTrace();
}
}
return null;
}
The response:
Solved.
Response from Postman:
Solved
Anyone faced this issue? I need your help. Thanks.
**EDIT: ** Actually it was complete. Log.e() and System.out.println(); methods doesn't show complete JSON.

Related

See response in API call which returns an unsuitable response

I have this method:
public Response issueConfirmation(String issueUrl) {
try {
ParameterizedTypeReference<Response> tRef = new ParameterizedTypeReference<Response>() {
};
HttpHeaders headers = createHeaders();
headers.add(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE);
HttpEntity<String> request = new HttpEntity<>(headers);
ResponseEntity<Response> res = restTemplate.exchange(myUrl,
HttpMethod.GET, request, tRef);
if (res.getStatusCode().is2xxSuccessful()) {
LOG.debug("Request successful.");
return response.getBody();
} else {
return null; // tbc
}
} catch (RestClientException e) {
LOG.debug("RestClientException: {} {}", e.getMessage());
}
return null; // tbc
}
The format of myUrl is http://localhost:8081/issueConfirmation?customer=1234&order=5678&dob=01/01/1990.
If the URL contains an incorrect dob an unsuitable response message is returned and a RestClientException is thrown. This is the message in the exception:
Could not extract response: no suitable HttpMessageConverter found for response type [class com.avis.myapi.model.Response] and content type [text/html;charset=utf-8]
Part of the issue here seems to be that I'm expecting application/json but the response is text/html.
How can I see the response from my GET?

OkHttp returns 403 as response

I'm trying to make a request to the Third-party API, but I'm running into some issues using OkHTTP.
I'm using AWS4Signer to sign the request. I'm able to generate the credentials for the same.
Request<Void> requestAws = new DefaultRequest<Void>("sts");
requestAws.setHttpMethod(HttpMethodName.POST);
requestAws.setEndpoint(URI.create("third pary api call which uses https"));
requestAws.addHeader("x-amz-security-token", sessionCredentials.getSessionToken());
requestAws.addHeader("Content-Type", "application/json");
//sign the request
AWS4Signer signer = new AWS4Signer();
signer.setServiceName(Constant.SERVICE_NAME);
signer.setRegionName(Constant.AWS_REGION);
signer.sign(requestAws, new AWSCredentials() {
#Override
public String getAWSSecretKey() {
return sessionCredentials.getAccessKeyId();
}
#Override
public String getAWSAccessKeyId() {
return sessionCredentials.getSecretAccessKey();
}
});
Map<String, String> headers = requestAws.getHeaders();
String x_date = null;
String x_token = null;
String authorization = null;
String x_content = null;
//get and assign values
for (Map.Entry<String, String> entry : headers.entrySet()) {
if (entry.getKey().equals("x-amz-security-token")) {
x_token = entry.getValue();
}
if (entry.getKey().equals("X-Amz-Date")) {
x_date = entry.getValue();
}
if (entry.getKey().equals("Authorization")) {
authorization = entry.getValue();
}
}
logger.info("Headers body response: " + JsonUtils.jsonize(headers));
String json = objectMapper.writeValueAsString(emailRequestBody);
postHandler.post(x_date, x_token, authorization, json);
Below is the request code of okHTTP
String post(String x_date, String x_token, String authorization, String json) throws IOException {
RequestBody body = RequestBody.create(json, JSON);
Request request = new Request.Builder()
.url("https url is here")
.addHeader("Content-Type", "application/json")
.addHeader("X-Amz-Date", x_date)
.addHeader("x-amz-security-token", x_token)
.addHeader("Authorization", authorization)
.post(body)
.build();
try (Response response = client.newCall(request).execute()) {
return response.body().string();
}
}
Below is how the request looks like with headers:
Request{method=POST, url=https://cbc.com/api/send/email, headers=[Content-Type:application/json, X-Amz-Date:20220125T111056Z, x-amz-security-token:FwoGZXIvYXdzEHUaDF6/kQ0g7Mog7W1f7CK0ATG5xhFIXP34wRjziAkJKhw9vE5cbADBOpji7uqtLp5GLGLay+e9O2deFRB4eSpUMOOThDCEQg1tum43iX4a+8Kikuc3fv5gDjbMrdLJYAK3piYVbOAET8BAXdDdkPZVG+nNu31cEWZe9HC60svIj0m95YZ9Xx5rBIDm0AVWtj4JRCmonNm1ymCNRB4GTjhEzgnxlkqEYfdUivFdlORq/IlIssUzzV04fkr0kiqDiE9GrmU51ijAtb+PBjIt9MWbM8+x4z+y+IV4JFjuK4zrVW3Iaw4xUG/C+mpcCrZrunh+8fWgVTR6In1r, Authorization:AWS4-HMAC-SHA256 Credential=medS2y7xvISbOf7ke3IWthyCMV5koeTDD5r3gkxJ/20220125/us-west-2/execute-api/aws4_request, SignedHeaders=content-type;host;x-amz-date;x-amz-security-token, Signature=d862c9ed8175770244e17fd3cb216c2a92138183ad427ed67fc5f284a1a75266]}
Below is the response:
Response{protocol=h2, code=403, message=, url=https://cbc.com/api/send/email}
Why the response is returning 403? Can someone help me what I missed? Thank you for your time.

Changing a 404 response for REST API to a 200 empty response

I have a Spring Boot application written in Java that is a REST API. This service (Svc A) calls a REST API service (Svc B) with is also a Spring Boot Application written in Java. Svc B returns a 404 status code when no data was found. I need to change this response to a 200 status code and return an empty response object. I am not sure if or how to do this.
I can catch the error and determine if the 404 is this no data found error. However, I don't know how to change the response to a 200 empty response.
I am using a FeignClient to call the service. This is the error code that catches the 404:
#Component
public class FeignErrorDecoder implements ErrorDecoder {
Logger logger = LoggerFactory.getLogger(this.getClass());
#Override
public Exception decode(String methodKey, Response response) {
Reader reader = null;
String messageText = null;
switch (response.status()){
case 400:
logger.error("Status code " + response.status() + ", methodKey = " + methodKey);
case 404:
{
logger.error("Error took place when using Feign client to send HTTP Request. Status code " + response.status() + ", methodKey = " + methodKey);
try {
reader = response.body().asReader();
//Easy way to read the stream and get a String object
String result = CharStreams.toString(reader);
logger.error("RESPONSE BODY: " + result);
ObjectMapper mapper = new ObjectMapper();
//just in case you missed an attribute in the Pojo
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
//init the Pojo
ExceptionMessage exceptionMessage = mapper.readValue(result,
ExceptionMessage.class);
messageText = exceptionMessage.getMessage();
logger.info("message: " + messageText);
} catch(IOException ex) {
logger.error(ex.getMessage());
}
finally {
try {
if (reader != null)
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return new ResponseStatusException(HttpStatus.valueOf(200), messageText);
}
default:
return new Exception(response.reason());
}
}
}
I can change the status code to a 200 and it returns a 200 but I need to the response to have an empty response object.
The above code will return this response body of an error response object:
{
"statusCd" : "200",
"message" : "The Location not found for given Location Number and Facility Type Code",
"detailDesc" : "The Location not found for given Location Number and Facility Type Code. Error Timestamp : 2020-01-31 18:19:13"
}
I need it to return a response body like this:
200 - Empty Response
{
"facilityNumber": "923",
"facilityTimeZone": null,
"facilityAbbr": null,
"scheduledOperations": []
}
In case 404 just try
return new ResponseStatusException(HttpStatus.valueOf(200));
For anyone that has to do something this crazy...here is my solution:
Removed the FeignErrorCode file.
Added an exception to ControllerAdvice class like this:
#ExceptionHandler(FeignException.class)
public ResponseEntity<?> handleFeignException(FeignException fe, WebRequest request) {
ErrorDetails errorDetails = new ErrorDetails(new Date(), HttpStatus.valueOf(fe.status()), fe.getMessage(), request.getDescription(false));
String response = fe.contentUTF8();
if(response != null) {
ScheduledOperationsViewResponse scheduledOperationsViewResponse = new ScheduledOperationsViewResponse();
if (response.contains("Scheduled") || response.contains("Location")) {
HttpHeaders headers = new HttpHeaders();
scheduledOperationsViewResponse.setFacilityNumber(request.getParameter("facilityNumber"));
return new ResponseEntity<ScheduledOperationsViewResponse>(scheduledOperationsViewResponse, headers, HttpStatus.OK);
}
}
return new ResponseEntity<>(errorDetails, errorDetails.getStatus());
}

restTemplate postForEntity sometimes leads into 400 Error

In my Android app I try to make a POST via restTemplate.postForEntity() but the first time I try to post the data I get a 400 error. After my timetrigger sync-method try to post the data again it works and I get 200. I don't think it's a backend problem, because I did a couple requests via Swagger and Postman on the same interface and all of them worked without a problem.
This is the error I get:
POST request for "<url>" resulted in 400 (); invoking error handler
org.springframework.web.client.HttpClientErrorException: 400
This is what I see at the postForEntity() when I'm debugging:
'java.lang.NullPointerException' Cannot evaluate org.springframework.http.ResponseEntity.toString()
This is the code:
public ResponseEntity<ArrayList> postServiceData(List<BasicService> attributes) {
HttpStatus status = null;
ResponseEntity<ArrayList> chargerServiceResponse = new ResponseEntity<ArrayList>(status);
try {
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
HttpEntity<?> entity = RestServiceUtils.getHttpEntity(attributes, context);
chargerServiceResponse = restTemplate.postForEntity(url, entity, ArrayList.class);
SynchronisationStorage synchronisationStorage = new SynchronisationStorage(context);
synchronisationStorage.updateLastSynchronisationDate();
loggingStorageDbHelper.logSuccess(R.string.logging_save_send_charger_service_to_backend, 1000);
} catch (HttpClientErrorException e) {
/* do stuff*/
}
}
To set the body and token:
#NonNull
public static HttpEntity<?> getHttpEntity(List attributes, Context context) {
HttpHeaders headers = new HttpHeaders();
try {
headers.set(ServiceAppConstants.HEADER_ACCEPT, ServiceAppConstants.MEDIATYPE_JSON);
UserStorage userStorage = new UserStorage(context);
String token = userStorage.getJsonWebToken();
headers.set(ServiceAppConstants.HEADER_SECURITY_TOKEN, token);
}catch (Exception ex){
Log.e(RestServiceUtils.class.getName(), "Exception ocurred while trying to set token to header", ex);
}
return new HttpEntity<Object>(attributes, headers);
}

okhttpclient for android and Laravel API

Currently building an Android App that has a Web Service. Trying to get data from the SQL Database using the okhttp3 but I'm getting a weird response and I can't figure it out. My API in Laravel is:
public function getAccount(Request $request, User $user)
{
$email = $request->input('email');
//$response = Users::find($email);
$response = DB::table('users')->where('email', $email)->first();
$count = count($response);
if($count == 0) {
return Response::json([
'message' => 'An error occured',
], 401);
} else {
return Response::json([
'user' => $response->name,
'lastName' => $response->lastName,
'weight' => $response->weight,
'height' => $response->height,
'dob' => $response->DOB,
'email' => $response->email,
], 200);
}
And my Android code is:
private void getDetails() {
Thread thread = new Thread(new Runnable(){
public void run() {
OkHttpClient client = new OkHttpClient();
// Json string with email and password
String bodyString = "{\n\t\"email\" : \"" + email +"\"\n}";
// Make HTTP POST request
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, bodyString);
Request request = new Request.Builder()
.url("http://192.168.1.100/CAB398/public/api/auth/getAccount")
.post(body)
.addHeader("accept", "application/json")
.addHeader("content-type", "application/json")
//.addHeader("cache-control", "no-cache")
//.addHeader("postman-token", "c3d60511-7e0f-5155-b5ad-66031ad76578")
.build();
// execute request
try {
Response response = client.newCall(request).execute();
String responseData = response.body().toString();
// Response code 200 means login details found in DB
if(response.code() == 200){
etfirstName.setText(responseData);
} else if(response.code() == 401){
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
thread.start();
//wait for thread to finish
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
The issue is that I am getting the response of: okhttp3.internal.http.RealResponseBody#b8a47c8 as the response.body().toString(). I have tested the API call using postman and do get the correct response of:
{"user":"Joe","lastName":"smith","weight":108,"height":179,"dob":"1980-09-06","email":"JoeSmith#gmail.com"}
I think I am messing up the Request. Builder but I can't figure this out.
Cheers
Peter
You have mistaken the string() method from the ResponseBody object with the usual toString() method.. Here are some docs for it.
Just have:
String responseData = response.body().string();
instead of:
String responseData = response.body().toString();
You can find some info in here also

Categories